xref: /onnv-gate/usr/src/lib/libscf/common/scf_tmpl.c (revision 12967:ab9ae749152f)
17887SLiane.Praza@Sun.COM /*
27887SLiane.Praza@Sun.COM  * CDDL HEADER START
37887SLiane.Praza@Sun.COM  *
47887SLiane.Praza@Sun.COM  * The contents of this file are subject to the terms of the
57887SLiane.Praza@Sun.COM  * Common Development and Distribution License (the "License").
67887SLiane.Praza@Sun.COM  * You may not use this file except in compliance with the License.
77887SLiane.Praza@Sun.COM  *
87887SLiane.Praza@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97887SLiane.Praza@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107887SLiane.Praza@Sun.COM  * See the License for the specific language governing permissions
117887SLiane.Praza@Sun.COM  * and limitations under the License.
127887SLiane.Praza@Sun.COM  *
137887SLiane.Praza@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147887SLiane.Praza@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157887SLiane.Praza@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167887SLiane.Praza@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177887SLiane.Praza@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187887SLiane.Praza@Sun.COM  *
197887SLiane.Praza@Sun.COM  * CDDL HEADER END
207887SLiane.Praza@Sun.COM  */
217887SLiane.Praza@Sun.COM /*
22*12967Sgavin.maltby@oracle.com  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
237887SLiane.Praza@Sun.COM  */
247887SLiane.Praza@Sun.COM 
257887SLiane.Praza@Sun.COM /*
267887SLiane.Praza@Sun.COM  * scf_tmpl.c
277887SLiane.Praza@Sun.COM  *
287887SLiane.Praza@Sun.COM  * This file implements the bulk of the libscf templates interfaces.
297887SLiane.Praza@Sun.COM  * Templates describe metadata about a service or instance in general,
307887SLiane.Praza@Sun.COM  * and individual configuration properties on those services and instances.
317887SLiane.Praza@Sun.COM  * Human-consumable descriptions can be provided, along with definitions
327887SLiane.Praza@Sun.COM  * of valid configuration.  See service_bundle.dtd.1 for XML definitions
337887SLiane.Praza@Sun.COM  * of templates, and the svccfg code for information on how those definitions
347887SLiane.Praza@Sun.COM  * are translated into the repository.
357887SLiane.Praza@Sun.COM  *
367887SLiane.Praza@Sun.COM  * The main data structures are scf_pg_tmpl and scf_prop_tmpl.  These
377887SLiane.Praza@Sun.COM  * are allocated by the callers through scf_tmpl_[pg|prop]_create(), and
387887SLiane.Praza@Sun.COM  * destroyed with scf_tmpl_[pg|prop]_destroy().  They are populated by
397887SLiane.Praza@Sun.COM  * scf_tmpl_get_by_pg_name(), scf_tmpl_get_by_pg(), and
407887SLiane.Praza@Sun.COM  * scf_tmpl_get_by_prop().  They also store the iterator state for
417887SLiane.Praza@Sun.COM  * scf_tmpl_iter_pgs() and scf_tmpl_iter_props().
427887SLiane.Praza@Sun.COM  *
437887SLiane.Praza@Sun.COM  * These data structures are then consumed by other functions to
447887SLiane.Praza@Sun.COM  * gather information about the template (e.g. name, description,
457887SLiane.Praza@Sun.COM  * choices, constraints, etc.).
467887SLiane.Praza@Sun.COM  *
477887SLiane.Praza@Sun.COM  * scf_tmpl_validate_fmri() does instance validation against template
487887SLiane.Praza@Sun.COM  * data, and populates a set of template errors which can be explored using
497887SLiane.Praza@Sun.COM  * the scf_tmpl_next_error() and the scf_tmpl_error*() suite of functions.
507887SLiane.Praza@Sun.COM  *
517887SLiane.Praza@Sun.COM  * The main data structures for template errors are scf_tmpl_errors,
527887SLiane.Praza@Sun.COM  * defined in this file, and scf_tmpl_error, defined in libscf_priv.h.
537887SLiane.Praza@Sun.COM  * scf_tmpl_error is shared with svccfg to offer common printing
547887SLiane.Praza@Sun.COM  * of error messages between libscf and svccfg.
557887SLiane.Praza@Sun.COM  *
567887SLiane.Praza@Sun.COM  * General convenience functions are towards the top of this file,
577887SLiane.Praza@Sun.COM  * followed by pg and prop template discovery functions, followed
587887SLiane.Praza@Sun.COM  * by functions which gather information about the discovered
597887SLiane.Praza@Sun.COM  * template.  Validation and error functions are at the end of this file.
607887SLiane.Praza@Sun.COM  */
617887SLiane.Praza@Sun.COM 
627887SLiane.Praza@Sun.COM #include "lowlevel_impl.h"
637887SLiane.Praza@Sun.COM #include "libscf_impl.h"
647887SLiane.Praza@Sun.COM #include <assert.h>
657887SLiane.Praza@Sun.COM #include <errno.h>
667887SLiane.Praza@Sun.COM #include <libintl.h>
677887SLiane.Praza@Sun.COM #include <stdlib.h>
687887SLiane.Praza@Sun.COM #include <stdio.h>
697887SLiane.Praza@Sun.COM #include <strings.h>
707887SLiane.Praza@Sun.COM #include <locale.h>
717887SLiane.Praza@Sun.COM #include <ctype.h>
727887SLiane.Praza@Sun.COM #include <inttypes.h>
737887SLiane.Praza@Sun.COM 
747887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_COMMON_NAME_C	"common_name_C"
757887SLiane.Praza@Sun.COM 
767887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_NONE		0
777887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_INST		1
787887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_RESTARTER	2
797887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_GLOBAL		3
807887SLiane.Praza@Sun.COM 
817887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_NT		0
827887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_N		1
837887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_T		2
847887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_WILD	3
857887SLiane.Praza@Sun.COM 
867887SLiane.Praza@Sun.COM struct scf_pg_tmpl {
877887SLiane.Praza@Sun.COM 	int pt_populated;
887887SLiane.Praza@Sun.COM 	scf_handle_t *pt_h;
897887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pt_pg;
907887SLiane.Praza@Sun.COM 	scf_service_t *pt_orig_svc;
917887SLiane.Praza@Sun.COM 	scf_service_t *pt_svc;
927887SLiane.Praza@Sun.COM 	scf_instance_t *pt_orig_inst;
937887SLiane.Praza@Sun.COM 	scf_instance_t *pt_inst;
947887SLiane.Praza@Sun.COM 	scf_snapshot_t *pt_snap;
957887SLiane.Praza@Sun.COM 	int pt_is_iter;
967887SLiane.Praza@Sun.COM 	scf_iter_t *pt_iter;
977887SLiane.Praza@Sun.COM 	int pt_iter_last;
987887SLiane.Praza@Sun.COM };
997887SLiane.Praza@Sun.COM 
1007887SLiane.Praza@Sun.COM #define	SCF_WALK_ERROR		-1
1017887SLiane.Praza@Sun.COM #define	SCF_WALK_NEXT		0
1027887SLiane.Praza@Sun.COM #define	SCF_WALK_DONE		1
1037887SLiane.Praza@Sun.COM 
1047887SLiane.Praza@Sun.COM struct pg_tmpl_walk {
1057887SLiane.Praza@Sun.COM 	const char *pw_snapname;
1067887SLiane.Praza@Sun.COM 	const char *pw_pgname;
1077887SLiane.Praza@Sun.COM 	const char *pw_pgtype;
1087887SLiane.Praza@Sun.COM 	scf_instance_t *pw_inst;
1097887SLiane.Praza@Sun.COM 	scf_service_t *pw_svc;
1107887SLiane.Praza@Sun.COM 	scf_snapshot_t *pw_snap;
1117887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pw_pg;
1127887SLiane.Praza@Sun.COM 	const char *pw_target;
1137887SLiane.Praza@Sun.COM 	char *pw_tmpl_pgname;
1147887SLiane.Praza@Sun.COM };
1157887SLiane.Praza@Sun.COM 
1167887SLiane.Praza@Sun.COM typedef struct pg_tmpl_walk pg_tmpl_walk_t;
1177887SLiane.Praza@Sun.COM 
1187887SLiane.Praza@Sun.COM typedef int walk_template_inst_func_t(scf_service_t *_svc,
1197887SLiane.Praza@Sun.COM     scf_instance_t *_inst, pg_tmpl_walk_t *p);
1207887SLiane.Praza@Sun.COM 
1217887SLiane.Praza@Sun.COM struct scf_prop_tmpl {
1227887SLiane.Praza@Sun.COM 	int prt_populated;
1237887SLiane.Praza@Sun.COM 	scf_handle_t *prt_h;
1247887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *prt_t;
1257887SLiane.Praza@Sun.COM 	scf_propertygroup_t *prt_pg;
1267887SLiane.Praza@Sun.COM 	char *prt_pg_name;
1277887SLiane.Praza@Sun.COM 	scf_iter_t *prt_iter;
1287887SLiane.Praza@Sun.COM };
1297887SLiane.Praza@Sun.COM 
1307887SLiane.Praza@Sun.COM /*
1317887SLiane.Praza@Sun.COM  * Common server errors are usually passed back to the caller.  This
1327887SLiane.Praza@Sun.COM  * array defines them centrally so that they don't need to be enumerated
1337887SLiane.Praza@Sun.COM  * in every libscf call.
1347887SLiane.Praza@Sun.COM  */
1357887SLiane.Praza@Sun.COM static const scf_error_t errors_server[] = {
1367887SLiane.Praza@Sun.COM 	SCF_ERROR_BACKEND_ACCESS,
1377887SLiane.Praza@Sun.COM 	SCF_ERROR_CONNECTION_BROKEN,
1387887SLiane.Praza@Sun.COM 	SCF_ERROR_DELETED,
1397887SLiane.Praza@Sun.COM 	SCF_ERROR_HANDLE_DESTROYED,
1407887SLiane.Praza@Sun.COM 	SCF_ERROR_INTERNAL,
1417887SLiane.Praza@Sun.COM 	SCF_ERROR_NO_MEMORY,
1427887SLiane.Praza@Sun.COM 	SCF_ERROR_NO_RESOURCES,
1437887SLiane.Praza@Sun.COM 	SCF_ERROR_NOT_BOUND,
1447887SLiane.Praza@Sun.COM 	SCF_ERROR_PERMISSION_DENIED,
1457887SLiane.Praza@Sun.COM 	0
1467887SLiane.Praza@Sun.COM 	};
1477887SLiane.Praza@Sun.COM 
1487887SLiane.Praza@Sun.COM /*
1497887SLiane.Praza@Sun.COM  * int ismember()
1507887SLiane.Praza@Sun.COM  *
1517887SLiane.Praza@Sun.COM  * Returns 1 if the supplied error is a member of the error array, 0
1527887SLiane.Praza@Sun.COM  * if it is not.
1537887SLiane.Praza@Sun.COM  */
154*12967Sgavin.maltby@oracle.com int
ismember(const scf_error_t error,const scf_error_t error_array[])155*12967Sgavin.maltby@oracle.com ismember(const scf_error_t error, const scf_error_t error_array[])
1567887SLiane.Praza@Sun.COM {
1577887SLiane.Praza@Sun.COM 	int i;
1587887SLiane.Praza@Sun.COM 
1597887SLiane.Praza@Sun.COM 	for (i = 0; error_array[i] != 0; ++i) {
1607887SLiane.Praza@Sun.COM 		if (error == error_array[i])
1617887SLiane.Praza@Sun.COM 			return (1);
1627887SLiane.Praza@Sun.COM 	}
1637887SLiane.Praza@Sun.COM 
1647887SLiane.Praza@Sun.COM 	return (0);
1657887SLiane.Praza@Sun.COM }
1667887SLiane.Praza@Sun.COM 
1677887SLiane.Praza@Sun.COM /*
1687887SLiane.Praza@Sun.COM  * char *_scf_tmpl_get_fmri()
1697887SLiane.Praza@Sun.COM  *
1707887SLiane.Praza@Sun.COM  * Given a pg_tmpl, returns the FMRI of the service or instance that
1717887SLiane.Praza@Sun.COM  * template describes.  The allocated string must be freed with free().
1727887SLiane.Praza@Sun.COM  *
1737887SLiane.Praza@Sun.COM  * On failure, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
1747887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
1757887SLiane.Praza@Sun.COM  */
1767887SLiane.Praza@Sun.COM static char *
_scf_tmpl_get_fmri(const scf_pg_tmpl_t * t)1777887SLiane.Praza@Sun.COM _scf_tmpl_get_fmri(const scf_pg_tmpl_t *t)
1787887SLiane.Praza@Sun.COM {
1797887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1;
1807887SLiane.Praza@Sun.COM 	int r;
1817887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
1827887SLiane.Praza@Sun.COM 
1837887SLiane.Praza@Sun.COM 	assert(t->pt_svc != NULL || t->pt_inst != NULL);
1847887SLiane.Praza@Sun.COM 	assert(t->pt_svc == NULL || t->pt_inst == NULL);
1857887SLiane.Praza@Sun.COM 
1867887SLiane.Praza@Sun.COM 	if (buf == NULL) {
1877887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1887887SLiane.Praza@Sun.COM 		return (buf);
1897887SLiane.Praza@Sun.COM 	}
1907887SLiane.Praza@Sun.COM 
1917887SLiane.Praza@Sun.COM 	if (t->pt_inst != NULL)
1927887SLiane.Praza@Sun.COM 		r = scf_instance_to_fmri(t->pt_inst, buf, sz);
1937887SLiane.Praza@Sun.COM 	else
1947887SLiane.Praza@Sun.COM 		r = scf_service_to_fmri(t->pt_svc, buf, sz);
1957887SLiane.Praza@Sun.COM 
1967887SLiane.Praza@Sun.COM 	if (r == -1) {
1977887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
1987887SLiane.Praza@Sun.COM 			free(buf);
1997887SLiane.Praza@Sun.COM 			buf = NULL;
2007887SLiane.Praza@Sun.COM 		} else {
2017887SLiane.Praza@Sun.COM 			assert(0);
2027887SLiane.Praza@Sun.COM 			abort();
2037887SLiane.Praza@Sun.COM 		}
2047887SLiane.Praza@Sun.COM 	}
2057887SLiane.Praza@Sun.COM 
2067887SLiane.Praza@Sun.COM 	return (buf);
2077887SLiane.Praza@Sun.COM }
2087887SLiane.Praza@Sun.COM 
2097887SLiane.Praza@Sun.COM /*
2107887SLiane.Praza@Sun.COM  * char *_scf_get_pg_type()
2117887SLiane.Praza@Sun.COM  *
2127887SLiane.Praza@Sun.COM  * Given a propertygroup, returns an allocated string containing the
2137887SLiane.Praza@Sun.COM  * type.  The string must be freed with free().
2147887SLiane.Praza@Sun.COM  *
2157887SLiane.Praza@Sun.COM  * On failure, returns NULL and sets scf_error() to: _CONNECTION_BROKEN,
2167887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
2177887SLiane.Praza@Sun.COM  */
2187887SLiane.Praza@Sun.COM static char *
_scf_get_pg_type(scf_propertygroup_t * pg)2197887SLiane.Praza@Sun.COM _scf_get_pg_type(scf_propertygroup_t *pg)
2207887SLiane.Praza@Sun.COM {
2217887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
2227887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
2237887SLiane.Praza@Sun.COM 
2247887SLiane.Praza@Sun.COM 	if (buf == NULL) {
2257887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2267887SLiane.Praza@Sun.COM 	} else if (scf_pg_get_type(pg, buf, sz) == -1) {
2277887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
2287887SLiane.Praza@Sun.COM 			free(buf);
2297887SLiane.Praza@Sun.COM 			buf = NULL;
2307887SLiane.Praza@Sun.COM 		} else {
2317887SLiane.Praza@Sun.COM 			assert(0);
2327887SLiane.Praza@Sun.COM 			abort();
2337887SLiane.Praza@Sun.COM 		}
2347887SLiane.Praza@Sun.COM 	}
2357887SLiane.Praza@Sun.COM 
2367887SLiane.Praza@Sun.COM 	return (buf);
2377887SLiane.Praza@Sun.COM }
2387887SLiane.Praza@Sun.COM 
2397887SLiane.Praza@Sun.COM /*
2407887SLiane.Praza@Sun.COM  * char *_scf_get_prop_name()
2417887SLiane.Praza@Sun.COM  *
2427887SLiane.Praza@Sun.COM  * Given a property, returns the name in an allocated string.  The string must
2437887SLiane.Praza@Sun.COM  * be freed with free().
2447887SLiane.Praza@Sun.COM  *
2457887SLiane.Praza@Sun.COM  * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
2467887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
2477887SLiane.Praza@Sun.COM  */
2487887SLiane.Praza@Sun.COM static char *
_scf_get_prop_name(scf_property_t * prop)2497887SLiane.Praza@Sun.COM _scf_get_prop_name(scf_property_t *prop)
2507887SLiane.Praza@Sun.COM {
2517887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
2527887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
2537887SLiane.Praza@Sun.COM 
2547887SLiane.Praza@Sun.COM 	if (buf == NULL) {
2557887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2567887SLiane.Praza@Sun.COM 	} else if (scf_property_get_name(prop, buf, sz) == -1) {
2577887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
2587887SLiane.Praza@Sun.COM 			free(buf);
2597887SLiane.Praza@Sun.COM 			buf = NULL;
2607887SLiane.Praza@Sun.COM 		} else {
2617887SLiane.Praza@Sun.COM 			assert(0);
2627887SLiane.Praza@Sun.COM 			abort();
2637887SLiane.Praza@Sun.COM 		}
2647887SLiane.Praza@Sun.COM 	}
2657887SLiane.Praza@Sun.COM 
2667887SLiane.Praza@Sun.COM 	return (buf);
2677887SLiane.Praza@Sun.COM }
2687887SLiane.Praza@Sun.COM 
2697887SLiane.Praza@Sun.COM /*
2707887SLiane.Praza@Sun.COM  * char *_scf_get_prop_type()
2717887SLiane.Praza@Sun.COM  *
2727887SLiane.Praza@Sun.COM  * Given a property, returns the type in an allocated string.  The string must
2737887SLiane.Praza@Sun.COM  * be freed with free().
2747887SLiane.Praza@Sun.COM  *
2757887SLiane.Praza@Sun.COM  * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
2767887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
2777887SLiane.Praza@Sun.COM  */
2787887SLiane.Praza@Sun.COM static char *
_scf_get_prop_type(scf_property_t * prop)2797887SLiane.Praza@Sun.COM _scf_get_prop_type(scf_property_t *prop)
2807887SLiane.Praza@Sun.COM {
2817887SLiane.Praza@Sun.COM 	scf_type_t type;
2827887SLiane.Praza@Sun.COM 	char *ret;
2837887SLiane.Praza@Sun.COM 
2847887SLiane.Praza@Sun.COM 	if (scf_property_type(prop, &type) == -1) {
2857887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
2867887SLiane.Praza@Sun.COM 			return (NULL);
2877887SLiane.Praza@Sun.COM 		} else {
2887887SLiane.Praza@Sun.COM 			assert(0);
2897887SLiane.Praza@Sun.COM 			abort();
2907887SLiane.Praza@Sun.COM 		}
2917887SLiane.Praza@Sun.COM 	}
2927887SLiane.Praza@Sun.COM 
2937887SLiane.Praza@Sun.COM 	ret = strdup(scf_type_to_string(type));
2947887SLiane.Praza@Sun.COM 	if (ret == NULL)
2957887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2967887SLiane.Praza@Sun.COM 
2977887SLiane.Praza@Sun.COM 	return (ret);
2987887SLiane.Praza@Sun.COM }
2997887SLiane.Praza@Sun.COM 
3007887SLiane.Praza@Sun.COM /*
3017887SLiane.Praza@Sun.COM  * int _read_single_value_from_pg()
3027887SLiane.Praza@Sun.COM  *
3037887SLiane.Praza@Sun.COM  * Reads a single value from the pg and property name specified.  On success,
3047887SLiane.Praza@Sun.COM  * returns an allocated value that must be freed.
3057887SLiane.Praza@Sun.COM  *
3067887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
3077887SLiane.Praza@Sun.COM  *  SCF_ERROR_BACKEND_ACCESS
3087887SLiane.Praza@Sun.COM  *  SCF_ERROR_CONNECTION_BROKEN
3097887SLiane.Praza@Sun.COM  *  SCF_ERROR_CONSTRAINT_VIOLATED
3107887SLiane.Praza@Sun.COM  *    Property has more than one value associated with it.
3117887SLiane.Praza@Sun.COM  *  SCF_ERROR_DELETED
3127887SLiane.Praza@Sun.COM  *  SCF_ERROR_HANDLE_DESTROYED
3137887SLiane.Praza@Sun.COM  *  SCF_ERROR_INTERNAL
3147887SLiane.Praza@Sun.COM  *  SCF_ERROR_INVALID_ARGUMENT
3157887SLiane.Praza@Sun.COM  *    prop_name not a valid property name.
3167887SLiane.Praza@Sun.COM  *  SCF_ERROR_NO_MEMORY
3177887SLiane.Praza@Sun.COM  *  SCF_ERROR_NO_RESOURCES
3187887SLiane.Praza@Sun.COM  *  SCF_ERROR_NOT_BOUND
3197887SLiane.Praza@Sun.COM  *  SCF_ERROR_NOT_FOUND
3207887SLiane.Praza@Sun.COM  *    Property doesn't exist or exists and has no value.
3217887SLiane.Praza@Sun.COM  *  SCF_ERROR_NOT_SET
3227887SLiane.Praza@Sun.COM  *    Property group specified by pg is not set.
3237887SLiane.Praza@Sun.COM  *  SCF_ERROR_PERMISSION_DENIED
3247887SLiane.Praza@Sun.COM  */
3257887SLiane.Praza@Sun.COM static int
_read_single_value_from_pg(scf_propertygroup_t * pg,const char * prop_name,scf_value_t ** val)3267887SLiane.Praza@Sun.COM _read_single_value_from_pg(scf_propertygroup_t *pg, const char *prop_name,
3277887SLiane.Praza@Sun.COM     scf_value_t **val)
3287887SLiane.Praza@Sun.COM {
3297887SLiane.Praza@Sun.COM 	scf_handle_t *h;
3307887SLiane.Praza@Sun.COM 	scf_property_t *prop;
3317887SLiane.Praza@Sun.COM 	int ret = 0;
3327887SLiane.Praza@Sun.COM 
3337887SLiane.Praza@Sun.COM 	assert(val != NULL);
3347887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
3357887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
3367887SLiane.Praza@Sun.COM 		return (-1);
3377887SLiane.Praza@Sun.COM 	}
3387887SLiane.Praza@Sun.COM 
3397887SLiane.Praza@Sun.COM 	prop = scf_property_create(h);
3407887SLiane.Praza@Sun.COM 	*val = scf_value_create(h);
3417887SLiane.Praza@Sun.COM 
3427887SLiane.Praza@Sun.COM 	if (prop == NULL || *val == NULL) {
3437887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
3447887SLiane.Praza@Sun.COM 		goto read_single_value_from_pg_fail;
3457887SLiane.Praza@Sun.COM 	}
3467887SLiane.Praza@Sun.COM 
3477887SLiane.Praza@Sun.COM 	if (scf_pg_get_property(pg, prop_name, prop) != 0) {
3487887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
3497887SLiane.Praza@Sun.COM 		goto read_single_value_from_pg_fail;
3507887SLiane.Praza@Sun.COM 	}
3517887SLiane.Praza@Sun.COM 
3527887SLiane.Praza@Sun.COM 	if (scf_property_get_value(prop, *val) == -1) {
3537887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
3547887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
3557887SLiane.Praza@Sun.COM 		goto read_single_value_from_pg_fail;
3567887SLiane.Praza@Sun.COM 	}
3577887SLiane.Praza@Sun.COM 
3587887SLiane.Praza@Sun.COM 	goto read_single_value_from_pg_done;
3597887SLiane.Praza@Sun.COM 
3607887SLiane.Praza@Sun.COM read_single_value_from_pg_fail:
3617887SLiane.Praza@Sun.COM 	scf_value_destroy(*val);
3627887SLiane.Praza@Sun.COM 	*val = NULL;
3637887SLiane.Praza@Sun.COM 	ret = -1;
3647887SLiane.Praza@Sun.COM 
3657887SLiane.Praza@Sun.COM read_single_value_from_pg_done:
3667887SLiane.Praza@Sun.COM 	scf_property_destroy(prop);
3677887SLiane.Praza@Sun.COM 	return (ret);
3687887SLiane.Praza@Sun.COM }
3697887SLiane.Praza@Sun.COM 
3707887SLiane.Praza@Sun.COM /*
3717887SLiane.Praza@Sun.COM  * char *_scf_read_single_astring_from_pg()
3727887SLiane.Praza@Sun.COM  *
3737887SLiane.Praza@Sun.COM  * Reads an astring from the pg and property name specified.  On success,
3747887SLiane.Praza@Sun.COM  * returns an allocated string.  The string must be freed with free().
3757887SLiane.Praza@Sun.COM  *
3767887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
3777887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3787887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3797887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
3807887SLiane.Praza@Sun.COM  *     Property has more than one value associated with it.
3817887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3827887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3837887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3847887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
3857887SLiane.Praza@Sun.COM  *     prop_name not a valid property name.
3867887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3877887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3887887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3897887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3907887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3917887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
3927887SLiane.Praza@Sun.COM  *     The property group specified by pg is not set.
3937887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3947887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
3957887SLiane.Praza@Sun.COM  */
3967887SLiane.Praza@Sun.COM char *
_scf_read_single_astring_from_pg(scf_propertygroup_t * pg,const char * prop_name)3977887SLiane.Praza@Sun.COM _scf_read_single_astring_from_pg(scf_propertygroup_t *pg, const char *prop_name)
3987887SLiane.Praza@Sun.COM {
3997887SLiane.Praza@Sun.COM 	scf_value_t *val;
4007887SLiane.Praza@Sun.COM 	char *ret = NULL;
4017887SLiane.Praza@Sun.COM 	ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
4027887SLiane.Praza@Sun.COM 
4037887SLiane.Praza@Sun.COM 	assert(rsize != 0);
4047887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(pg, prop_name, &val) == -1)
4057887SLiane.Praza@Sun.COM 		return (NULL);
4067887SLiane.Praza@Sun.COM 
4077887SLiane.Praza@Sun.COM 	ret = malloc(rsize);
4087887SLiane.Praza@Sun.COM 	if (ret == NULL) {
4097887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4107887SLiane.Praza@Sun.COM 		goto cleanup;
4117887SLiane.Praza@Sun.COM 	}
4127887SLiane.Praza@Sun.COM 
4137887SLiane.Praza@Sun.COM 	if (scf_value_get_astring(val, ret, rsize) < 0) {
4147887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
4157887SLiane.Praza@Sun.COM 		free(ret);
4167887SLiane.Praza@Sun.COM 		ret = NULL;
4177887SLiane.Praza@Sun.COM 	}
4187887SLiane.Praza@Sun.COM 
4197887SLiane.Praza@Sun.COM cleanup:
4207887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
4217887SLiane.Praza@Sun.COM 	return (ret);
4227887SLiane.Praza@Sun.COM }
4237887SLiane.Praza@Sun.COM 
4247887SLiane.Praza@Sun.COM /*
4257887SLiane.Praza@Sun.COM  * char *_scf_read_tmpl_prop_type_as_string()
4267887SLiane.Praza@Sun.COM  *
4277887SLiane.Praza@Sun.COM  * Reads the property type and returns it as an allocated string.  The string
4287887SLiane.Praza@Sun.COM  * must be freed with free().
4297887SLiane.Praza@Sun.COM  *
4307887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _BACKEND_ACCESS,
4317887SLiane.Praza@Sun.COM  * _CONNECTION_BROKEN, _DELETED, _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY,
4327887SLiane.Praza@Sun.COM  * _NO_RESOURCES, _NOT_BOUND, _PERMISSION_DENIED, or _TEMPLATE_INVALID.
4337887SLiane.Praza@Sun.COM  */
4347887SLiane.Praza@Sun.COM char *
_scf_read_tmpl_prop_type_as_string(const scf_prop_tmpl_t * pt)4357887SLiane.Praza@Sun.COM _scf_read_tmpl_prop_type_as_string(const scf_prop_tmpl_t *pt)
4367887SLiane.Praza@Sun.COM {
4377887SLiane.Praza@Sun.COM 	char *type;
4387887SLiane.Praza@Sun.COM 
4397887SLiane.Praza@Sun.COM 	type = _scf_read_single_astring_from_pg(pt->prt_pg,
4407887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TYPE);
4417887SLiane.Praza@Sun.COM 	if (type == NULL) {
4427887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
4437887SLiane.Praza@Sun.COM 			return (NULL);
4447887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
4457887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
4467887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
4477887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
4487887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
4497887SLiane.Praza@Sun.COM 			return (NULL);
4507887SLiane.Praza@Sun.COM 
4517887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
4527887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
4537887SLiane.Praza@Sun.COM 		default:
4547887SLiane.Praza@Sun.COM 			assert(0);
4557887SLiane.Praza@Sun.COM 			abort();
4567887SLiane.Praza@Sun.COM 		}
4577887SLiane.Praza@Sun.COM 	}
4587887SLiane.Praza@Sun.COM 
4597887SLiane.Praza@Sun.COM 	return (type);
4607887SLiane.Praza@Sun.COM }
4617887SLiane.Praza@Sun.COM 
4627887SLiane.Praza@Sun.COM /*
4637887SLiane.Praza@Sun.COM  * int _read_single_boolean_from_pg()
4647887SLiane.Praza@Sun.COM  *
4657887SLiane.Praza@Sun.COM  * Reads a boolean from the pg and property name specified.
4667887SLiane.Praza@Sun.COM  *
4677887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
4687887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
4697887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
4707887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
4717887SLiane.Praza@Sun.COM  *     Property has more than one value associated with it.
4727887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
4737887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
4747887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
4757887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
4767887SLiane.Praza@Sun.COM  *     prop_name is not a valid property name.
4777887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
4797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
4807887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
4817887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
4827887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
4837887SLiane.Praza@Sun.COM  *     The property group specified by pg is not set.
4847887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
4857887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
4867887SLiane.Praza@Sun.COM  */
4877887SLiane.Praza@Sun.COM static int
_read_single_boolean_from_pg(scf_propertygroup_t * pg,const char * prop_name,uint8_t * bool)4887887SLiane.Praza@Sun.COM _read_single_boolean_from_pg(scf_propertygroup_t *pg, const char *prop_name,
4897887SLiane.Praza@Sun.COM     uint8_t *bool)
4907887SLiane.Praza@Sun.COM {
4917887SLiane.Praza@Sun.COM 	scf_value_t *val;
4927887SLiane.Praza@Sun.COM 	int ret = 0;
4937887SLiane.Praza@Sun.COM 
4947887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(pg, prop_name, &val) == -1)
4957887SLiane.Praza@Sun.COM 		return (-1);
4967887SLiane.Praza@Sun.COM 
4977887SLiane.Praza@Sun.COM 	if (scf_value_get_boolean(val, bool) < 0) {
4987887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
4997887SLiane.Praza@Sun.COM 		ret = -1;
5007887SLiane.Praza@Sun.COM 	}
5017887SLiane.Praza@Sun.COM 
5027887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
5037887SLiane.Praza@Sun.COM 	return (ret);
5047887SLiane.Praza@Sun.COM }
5057887SLiane.Praza@Sun.COM 
5067887SLiane.Praza@Sun.COM /*
507*12967Sgavin.maltby@oracle.com  * static char ** _append_astrings_values()
5087887SLiane.Praza@Sun.COM  *
5097887SLiane.Praza@Sun.COM  * This function reads the values from the property prop_name in pg and
5107887SLiane.Praza@Sun.COM  * appends to an existing scf_values_t *vals.  vals may be empty, but
5117887SLiane.Praza@Sun.COM  * must exist.  The function skips over zero-length and duplicate values.
5127887SLiane.Praza@Sun.COM  *
5137887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
5147887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5157887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5167887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5177887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5187887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5197887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
5207887SLiane.Praza@Sun.COM  *     prop_name is not a valid property name.
5217887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5227887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5237887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5247887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
5257887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
5267887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5277887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
5287887SLiane.Praza@Sun.COM  */
5297887SLiane.Praza@Sun.COM static char **
_append_astrings_values(scf_propertygroup_t * pg,const char * prop_name,scf_values_t * vals)5307887SLiane.Praza@Sun.COM _append_astrings_values(scf_propertygroup_t *pg, const char *prop_name,
5317887SLiane.Praza@Sun.COM     scf_values_t *vals)
5327887SLiane.Praza@Sun.COM {
5337887SLiane.Praza@Sun.COM 	scf_handle_t *h;
5347887SLiane.Praza@Sun.COM 	scf_property_t *prop;
5357887SLiane.Praza@Sun.COM 	scf_value_t *val;
5367887SLiane.Praza@Sun.COM 	scf_iter_t *iter;
5377887SLiane.Praza@Sun.COM 	ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
5387887SLiane.Praza@Sun.COM 	int err, count, cursz, i;
5397887SLiane.Praza@Sun.COM 
5407887SLiane.Praza@Sun.COM 	assert(vals != NULL);
5417887SLiane.Praza@Sun.COM 	assert(vals->value_type == SCF_TYPE_ASTRING);
5427887SLiane.Praza@Sun.COM 	assert(vals->reserved == NULL);
5437887SLiane.Praza@Sun.COM 	count = vals->value_count;
5447887SLiane.Praza@Sun.COM 	if (count == 0) {
5457887SLiane.Praza@Sun.COM 		cursz = 8;
5467887SLiane.Praza@Sun.COM 		vals->values.v_astring = calloc(cursz, sizeof (char *));
5477887SLiane.Praza@Sun.COM 		if (vals->values.v_astring == NULL) {
5487887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5497887SLiane.Praza@Sun.COM 			return (NULL);
5507887SLiane.Praza@Sun.COM 		}
5517887SLiane.Praza@Sun.COM 	} else {
5527887SLiane.Praza@Sun.COM 		/*
5537887SLiane.Praza@Sun.COM 		 * The array may be bigger, but it is irrelevant since
5547887SLiane.Praza@Sun.COM 		 * we will always re-allocate a new one.
5557887SLiane.Praza@Sun.COM 		 */
5567887SLiane.Praza@Sun.COM 		cursz = count;
5577887SLiane.Praza@Sun.COM 	}
5587887SLiane.Praza@Sun.COM 
5597887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
5607887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
5617887SLiane.Praza@Sun.COM 		return (NULL);
5627887SLiane.Praza@Sun.COM 	}
5637887SLiane.Praza@Sun.COM 
5647887SLiane.Praza@Sun.COM 	prop = scf_property_create(h);
5657887SLiane.Praza@Sun.COM 	val = scf_value_create(h);
5667887SLiane.Praza@Sun.COM 	iter = scf_iter_create(h);
5677887SLiane.Praza@Sun.COM 
5687887SLiane.Praza@Sun.COM 	if (prop == NULL || val == NULL || iter == NULL) {
5697887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
5707887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
5717887SLiane.Praza@Sun.COM 	}
5727887SLiane.Praza@Sun.COM 
5737887SLiane.Praza@Sun.COM 	if (scf_pg_get_property(pg, prop_name, prop) != 0) {
5747887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
5757887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
5767887SLiane.Praza@Sun.COM 	}
5777887SLiane.Praza@Sun.COM 
5787887SLiane.Praza@Sun.COM 	if (scf_iter_property_values(iter, prop) != 0) {
5797887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
5807887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
5817887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
5827887SLiane.Praza@Sun.COM 	}
5837887SLiane.Praza@Sun.COM 
5847887SLiane.Praza@Sun.COM 	while ((err = scf_iter_next_value(iter, val)) == 1) {
5857887SLiane.Praza@Sun.COM 		int flag;
5867887SLiane.Praza@Sun.COM 		int r;
5877887SLiane.Praza@Sun.COM 
5887887SLiane.Praza@Sun.COM 		if (count + 1 >= cursz) {
5897887SLiane.Praza@Sun.COM 			void *aux;
5907887SLiane.Praza@Sun.COM 
5917887SLiane.Praza@Sun.COM 			cursz *= 2;
5927887SLiane.Praza@Sun.COM 			if ((aux = calloc(cursz, sizeof (char *))) == NULL) {
5937887SLiane.Praza@Sun.COM 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5947887SLiane.Praza@Sun.COM 				goto append_single_astring_from_pg_fail;
5957887SLiane.Praza@Sun.COM 			}
5967887SLiane.Praza@Sun.COM 			(void) memcpy(aux, vals->values.v_astring,
5977887SLiane.Praza@Sun.COM 			    count * sizeof (char *));
5987887SLiane.Praza@Sun.COM 			free(vals->values.v_astring);
5997887SLiane.Praza@Sun.COM 			vals->values.v_astring = aux;
6007887SLiane.Praza@Sun.COM 		}
6017887SLiane.Praza@Sun.COM 
6027887SLiane.Praza@Sun.COM 		vals->values.v_astring[count] = malloc(rsize);
6037887SLiane.Praza@Sun.COM 		if (vals->values.v_astring[count] == NULL) {
6047887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
6057887SLiane.Praza@Sun.COM 			goto append_single_astring_from_pg_fail;
6067887SLiane.Praza@Sun.COM 		}
6077887SLiane.Praza@Sun.COM 
6087887SLiane.Praza@Sun.COM 		if ((r = scf_value_get_astring(val,
6097887SLiane.Praza@Sun.COM 		    vals->values.v_astring[count], rsize)) <= 0) {
6107887SLiane.Praza@Sun.COM 			/* discard zero length strings */
6117887SLiane.Praza@Sun.COM 			if (r == 0) {
6127887SLiane.Praza@Sun.COM 				free(vals->values.v_astring[count]);
6137887SLiane.Praza@Sun.COM 				continue;
6147887SLiane.Praza@Sun.COM 			}
6157887SLiane.Praza@Sun.COM 			assert(scf_error() != SCF_ERROR_NOT_SET);
6167887SLiane.Praza@Sun.COM 			goto append_single_astring_from_pg_fail;
6177887SLiane.Praza@Sun.COM 		}
6187887SLiane.Praza@Sun.COM 		for (i = 0, flag = 0; i < count; ++i) {
6197887SLiane.Praza@Sun.COM 			/* find  and discard duplicates */
6207887SLiane.Praza@Sun.COM 			if (strncmp(vals->values.v_astring[i],
6217887SLiane.Praza@Sun.COM 			    vals->values.v_astring[count], rsize) == 0) {
6227887SLiane.Praza@Sun.COM 				free(vals->values.v_astring[count]);
6237887SLiane.Praza@Sun.COM 				flag = 1;
6247887SLiane.Praza@Sun.COM 				break;
6257887SLiane.Praza@Sun.COM 			}
6267887SLiane.Praza@Sun.COM 		}
6277887SLiane.Praza@Sun.COM 		if (flag == 1)
6287887SLiane.Praza@Sun.COM 			continue;
6297887SLiane.Praza@Sun.COM 
6307887SLiane.Praza@Sun.COM 		count++;
6317887SLiane.Praza@Sun.COM 	}
6327887SLiane.Praza@Sun.COM 
6337887SLiane.Praza@Sun.COM 	vals->value_count = count;
6347887SLiane.Praza@Sun.COM 
6357887SLiane.Praza@Sun.COM 	if (err != 0) {
6367887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
6377887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
6387887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
6397887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
6407887SLiane.Praza@Sun.COM 	} else {
6417887SLiane.Praza@Sun.COM 		vals->values_as_strings = vals->values.v_astring;
6427887SLiane.Praza@Sun.COM 	}
6437887SLiane.Praza@Sun.COM 
6447887SLiane.Praza@Sun.COM 	goto append_single_astring_from_pg_done;
6457887SLiane.Praza@Sun.COM 
6467887SLiane.Praza@Sun.COM append_single_astring_from_pg_fail:
6477887SLiane.Praza@Sun.COM 	for (i = 0; i <= count; ++i) {
6487887SLiane.Praza@Sun.COM 		if (vals->values.v_astring[i] != NULL)
6497887SLiane.Praza@Sun.COM 			free(vals->values.v_astring[i]);
6507887SLiane.Praza@Sun.COM 		vals->values.v_astring[i] = NULL;
6517887SLiane.Praza@Sun.COM 	}
6527887SLiane.Praza@Sun.COM 	free(vals->values.v_astring);
6537887SLiane.Praza@Sun.COM 	vals->values.v_astring = NULL;
6547887SLiane.Praza@Sun.COM 	vals->value_count = 0;
6557887SLiane.Praza@Sun.COM 
6567887SLiane.Praza@Sun.COM append_single_astring_from_pg_done:
6577887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
6587887SLiane.Praza@Sun.COM 	scf_property_destroy(prop);
6597887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
6607887SLiane.Praza@Sun.COM 	return (vals->values.v_astring);
6617887SLiane.Praza@Sun.COM }
6627887SLiane.Praza@Sun.COM 
6637887SLiane.Praza@Sun.COM /*
6647887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
6657887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
6667887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
6677887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
6687887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
6697887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
6707887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
6717887SLiane.Praza@Sun.COM  *     prop_name is not a valid property name.
6727887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
6737887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
6747887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
6757887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
6767887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
6777887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
6787887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
6797887SLiane.Praza@Sun.COM  */
6807887SLiane.Praza@Sun.COM static char **
_read_astrings_values(scf_propertygroup_t * pg,const char * prop_name,scf_values_t * vals)6817887SLiane.Praza@Sun.COM _read_astrings_values(scf_propertygroup_t *pg, const char *prop_name,
6827887SLiane.Praza@Sun.COM     scf_values_t *vals)
6837887SLiane.Praza@Sun.COM {
6847887SLiane.Praza@Sun.COM 	assert(vals != NULL);
6857887SLiane.Praza@Sun.COM 	vals->value_count = 0;
6867887SLiane.Praza@Sun.COM 	vals->value_type = SCF_TYPE_ASTRING;
6877887SLiane.Praza@Sun.COM 	vals->reserved = NULL;
6887887SLiane.Praza@Sun.COM 	return (_append_astrings_values(pg, prop_name, vals));
6897887SLiane.Praza@Sun.COM }
6907887SLiane.Praza@Sun.COM 
6917887SLiane.Praza@Sun.COM void
_scf_sanitize_locale(char * locale)6927887SLiane.Praza@Sun.COM _scf_sanitize_locale(char *locale)
6937887SLiane.Praza@Sun.COM {
6947887SLiane.Praza@Sun.COM 	for (; *locale != '\0'; locale++)
6957887SLiane.Praza@Sun.COM 		if (!isalnum(*locale) && *locale != '_')
6967887SLiane.Praza@Sun.COM 			*locale = '_';
6977887SLiane.Praza@Sun.COM }
6987887SLiane.Praza@Sun.COM 
6997887SLiane.Praza@Sun.COM /*
7007887SLiane.Praza@Sun.COM  * The returned string needs to be freed by the caller
7017887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error() to:
7027887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
7037887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
7047887SLiane.Praza@Sun.COM  *     Name isn't short enough to add the locale to.
7057887SLiane.Praza@Sun.COM  */
7067887SLiane.Praza@Sun.COM static char *
_add_locale_to_name(const char * name,const char * locale)7077887SLiane.Praza@Sun.COM _add_locale_to_name(const char *name, const char *locale)
7087887SLiane.Praza@Sun.COM {
7097887SLiane.Praza@Sun.COM 	char *lname = NULL;
7107887SLiane.Praza@Sun.COM 	ssize_t lsz;
7117887SLiane.Praza@Sun.COM 	char *loc;
7127887SLiane.Praza@Sun.COM 
7137887SLiane.Praza@Sun.COM 	if (locale == NULL)
7147887SLiane.Praza@Sun.COM 		locale = setlocale(LC_MESSAGES, NULL);
7157887SLiane.Praza@Sun.COM 	loc = strdup(locale);
7167887SLiane.Praza@Sun.COM 	if (loc == NULL) {
7177887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
7187887SLiane.Praza@Sun.COM 		return (NULL);
7197887SLiane.Praza@Sun.COM 	} else {
7207887SLiane.Praza@Sun.COM 		_scf_sanitize_locale(loc);
7217887SLiane.Praza@Sun.COM 	}
7227887SLiane.Praza@Sun.COM 
7237887SLiane.Praza@Sun.COM 	lsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
7247887SLiane.Praza@Sun.COM 	lname = malloc(lsz);
7257887SLiane.Praza@Sun.COM 	if (lname == NULL) {
7267887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
7277887SLiane.Praza@Sun.COM 		goto cleanup;
7287887SLiane.Praza@Sun.COM 	}
7297887SLiane.Praza@Sun.COM 
7307887SLiane.Praza@Sun.COM 	(void) strlcpy(lname, name, lsz);
7317887SLiane.Praza@Sun.COM 	if (strlcat(lname, loc, lsz) >= lsz) {
7327887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
7337887SLiane.Praza@Sun.COM 		free(lname);
7347887SLiane.Praza@Sun.COM 		lname = NULL;
7357887SLiane.Praza@Sun.COM 	}
7367887SLiane.Praza@Sun.COM cleanup:
7377887SLiane.Praza@Sun.COM 	free(loc);
7387887SLiane.Praza@Sun.COM 
7397887SLiane.Praza@Sun.COM 	return (lname);
7407887SLiane.Praza@Sun.COM }
7417887SLiane.Praza@Sun.COM 
7427887SLiane.Praza@Sun.COM /*
7437887SLiane.Praza@Sun.COM  * char *_tmpl_pg_name(pg, type, use_type)
7447887SLiane.Praza@Sun.COM  *
7457887SLiane.Praza@Sun.COM  * pg and type can both be NULL.  Returns the name of the most specific
7467887SLiane.Praza@Sun.COM  * template property group name based on the inputs.
7477887SLiane.Praza@Sun.COM  * If use_type is set and pg is not NULL, a property group name for a
7487887SLiane.Praza@Sun.COM  * property group template that has type defined is returned, even if no
7497887SLiane.Praza@Sun.COM  * type is provided.
7507887SLiane.Praza@Sun.COM  *
7517887SLiane.Praza@Sun.COM  * Returns NULL on failure and sets scf_error() to:
7527887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
7537887SLiane.Praza@Sun.COM  *     can't combine the arguments and get a reasonable length name
7547887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
7557887SLiane.Praza@Sun.COM  *
7567887SLiane.Praza@Sun.COM  */
7577887SLiane.Praza@Sun.COM static char *
_tmpl_pg_name(const char * pg,const char * type,int use_type)7587887SLiane.Praza@Sun.COM _tmpl_pg_name(const char *pg, const char *type, int use_type)
7597887SLiane.Praza@Sun.COM {
7607887SLiane.Praza@Sun.COM 	char *name;
7617887SLiane.Praza@Sun.COM 	ssize_t limit, size = 0;
7627887SLiane.Praza@Sun.COM 
7637887SLiane.Praza@Sun.COM 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
7647887SLiane.Praza@Sun.COM 	name = malloc(limit);
7657887SLiane.Praza@Sun.COM 	if (name == NULL) {
7667887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
7677887SLiane.Praza@Sun.COM 		return (NULL);
7687887SLiane.Praza@Sun.COM 	}
7697887SLiane.Praza@Sun.COM 
7707887SLiane.Praza@Sun.COM 	if (pg == NULL && type == NULL) {
7717887SLiane.Praza@Sun.COM 		if (strlcpy(name, SCF_PG_TM_PG_PATTERN_PREFIX, limit) >=
7727887SLiane.Praza@Sun.COM 		    limit) {
7737887SLiane.Praza@Sun.COM 			assert(0);
7747887SLiane.Praza@Sun.COM 			abort();
7757887SLiane.Praza@Sun.COM 		}
7767887SLiane.Praza@Sun.COM 		return (name);
7777887SLiane.Praza@Sun.COM 	} else if (pg != NULL && type != NULL) {
7787887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
7797887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg);
7807887SLiane.Praza@Sun.COM 	} else if (pg != NULL && type == NULL && use_type == 1) {
7817887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
7827887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg);
7837887SLiane.Praza@Sun.COM 	} else if (pg != NULL && type == NULL) {
7847887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
7857887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_N_PREFIX, pg);
7867887SLiane.Praza@Sun.COM 	} else if (type != NULL && pg == NULL) {
7877887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
7887887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_T_PREFIX, type);
7897887SLiane.Praza@Sun.COM 	} else {
7907887SLiane.Praza@Sun.COM 		assert(0);
7917887SLiane.Praza@Sun.COM 		abort();
7927887SLiane.Praza@Sun.COM 	}
7937887SLiane.Praza@Sun.COM 
7947887SLiane.Praza@Sun.COM 	if (size >= limit) {
7957887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
7967887SLiane.Praza@Sun.COM 		free(name);
7977887SLiane.Praza@Sun.COM 		return (NULL);
7987887SLiane.Praza@Sun.COM 	} else {
7997887SLiane.Praza@Sun.COM 		return (name);
8007887SLiane.Praza@Sun.COM 	}
8017887SLiane.Praza@Sun.COM }
8027887SLiane.Praza@Sun.COM 
8037887SLiane.Praza@Sun.COM /*
8047887SLiane.Praza@Sun.COM  * _scf_get_pg_name()
8057887SLiane.Praza@Sun.COM  * Gets the name of the supplied property group.  On success, returns an
8067887SLiane.Praza@Sun.COM  * allocated string.  The string must be freed by free().
8077887SLiane.Praza@Sun.COM  *
8087887SLiane.Praza@Sun.COM  * Returns NULL on failure and sets scf_error() to _CONNECTION_BROKEN,
8097887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
8107887SLiane.Praza@Sun.COM  */
8117887SLiane.Praza@Sun.COM static char *
_scf_get_pg_name(scf_propertygroup_t * pg)8127887SLiane.Praza@Sun.COM _scf_get_pg_name(scf_propertygroup_t *pg)
8137887SLiane.Praza@Sun.COM {
8147887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
8157887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
8167887SLiane.Praza@Sun.COM 
8177887SLiane.Praza@Sun.COM 	if (buf == NULL) {
8187887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
8197887SLiane.Praza@Sun.COM 	} else if (scf_pg_get_name(pg, buf, sz) == -1) {
8207887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
8217887SLiane.Praza@Sun.COM 			free(buf);
8227887SLiane.Praza@Sun.COM 			buf = NULL;
8237887SLiane.Praza@Sun.COM 		} else {
8247887SLiane.Praza@Sun.COM 			assert(0);
8257887SLiane.Praza@Sun.COM 			abort();
8267887SLiane.Praza@Sun.COM 		}
8277887SLiane.Praza@Sun.COM 	}
8287887SLiane.Praza@Sun.COM 
8297887SLiane.Praza@Sun.COM 	return (buf);
8307887SLiane.Praza@Sun.COM }
8317887SLiane.Praza@Sun.COM 
8327887SLiane.Praza@Sun.COM /*
8337887SLiane.Praza@Sun.COM  * char *_tmpl_prop_name()
8347887SLiane.Praza@Sun.COM  *
8357887SLiane.Praza@Sun.COM  * Returns the name of the property template prop (which is the name of
8367887SLiane.Praza@Sun.COM  * the property template property group) in the property group
8377887SLiane.Praza@Sun.COM  * template t. Returns NULL on failure and sets scf_error() to:
8387887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
8397887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
8407887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
8417887SLiane.Praza@Sun.COM  *     can't combine the arguments and get a reasonable length name
8427887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
8437887SLiane.Praza@Sun.COM  */
8447887SLiane.Praza@Sun.COM static char *
_tmpl_prop_name(const char * prop,scf_pg_tmpl_t * t)8457887SLiane.Praza@Sun.COM _tmpl_prop_name(const char *prop, scf_pg_tmpl_t *t)
8467887SLiane.Praza@Sun.COM {
8477887SLiane.Praza@Sun.COM 	char *name = NULL, *pg_name = NULL;
8487887SLiane.Praza@Sun.COM 	size_t prefix_size;
8497887SLiane.Praza@Sun.COM 	ssize_t limit, size = 0;
8507887SLiane.Praza@Sun.COM 
8517887SLiane.Praza@Sun.COM 	assert(prop != NULL);
8527887SLiane.Praza@Sun.COM 	assert(t->pt_pg != NULL);
8537887SLiane.Praza@Sun.COM 
8547887SLiane.Praza@Sun.COM 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
8557887SLiane.Praza@Sun.COM 	name = malloc(limit);
8567887SLiane.Praza@Sun.COM 	if (name == NULL) {
8577887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
8587887SLiane.Praza@Sun.COM 		return (NULL);
8597887SLiane.Praza@Sun.COM 	}
8607887SLiane.Praza@Sun.COM 
8617887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(t->pt_pg)) == NULL) {
8627887SLiane.Praza@Sun.COM 		free(name);
8637887SLiane.Praza@Sun.COM 		return (NULL);
8647887SLiane.Praza@Sun.COM 	}
8657887SLiane.Praza@Sun.COM 
8667887SLiane.Praza@Sun.COM 	prefix_size = strlen(SCF_PG_TM_PG_PAT_BASE);
8677887SLiane.Praza@Sun.COM 	if (strncmp(pg_name, SCF_PG_TM_PG_PAT_BASE, prefix_size) != 0) {
8687887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
8697887SLiane.Praza@Sun.COM 		free(name);
8707887SLiane.Praza@Sun.COM 		free(pg_name);
8717887SLiane.Praza@Sun.COM 		return (NULL);
8727887SLiane.Praza@Sun.COM 	}
8737887SLiane.Praza@Sun.COM 
8747887SLiane.Praza@Sun.COM 	size = snprintf(name, limit, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX,
8757887SLiane.Praza@Sun.COM 	    pg_name + prefix_size, prop);
8767887SLiane.Praza@Sun.COM 
8777887SLiane.Praza@Sun.COM 	if (size >= limit) {
8787887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
8797887SLiane.Praza@Sun.COM 		free(name);
8807887SLiane.Praza@Sun.COM 		free(pg_name);
8817887SLiane.Praza@Sun.COM 		return (NULL);
8827887SLiane.Praza@Sun.COM 	} else {
8837887SLiane.Praza@Sun.COM 		free(pg_name);
8847887SLiane.Praza@Sun.COM 		return (name);
8857887SLiane.Praza@Sun.COM 	}
8867887SLiane.Praza@Sun.COM }
8877887SLiane.Praza@Sun.COM 
8887887SLiane.Praza@Sun.COM /*
8897887SLiane.Praza@Sun.COM  *  int _get_snapshot()
8907887SLiane.Praza@Sun.COM  *
8917887SLiane.Praza@Sun.COM  *  Gets the specified snapshot.  If "snapshot" isn't defined, use the
8927887SLiane.Praza@Sun.COM  *  running snapshot.  If the snapshot isn't found, that may or may
8937887SLiane.Praza@Sun.COM  *  not be an error depending on the caller.  Return 0 in that case,
8947887SLiane.Praza@Sun.COM  *  but leave scf_error() set to SCF_ERROR_NOT_FOUND.  On all other
8957887SLiane.Praza@Sun.COM  *  errors, set scf_error() to:
8967887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
8977887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
8987887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
8997887SLiane.Praza@Sun.COM  *   SCF_ERR_HANDLE_DESTROYED
9007887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
9017887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
9027887SLiane.Praza@Sun.COM  *     The handle argument is NULL, or snaphot is not a valid snapshot name
9037887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
9047887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
9057887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
9067887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
9077887SLiane.Praza@Sun.COM  */
9087887SLiane.Praza@Sun.COM static int
_get_snapshot(scf_instance_t * inst,const char * snapshot,scf_snapshot_t ** snap)9097887SLiane.Praza@Sun.COM _get_snapshot(scf_instance_t *inst, const char *snapshot,
9107887SLiane.Praza@Sun.COM     scf_snapshot_t **snap)
9117887SLiane.Praza@Sun.COM {
9127887SLiane.Praza@Sun.COM 	int err;
9137887SLiane.Praza@Sun.COM 	scf_handle_t *h;
9147887SLiane.Praza@Sun.COM 
9157887SLiane.Praza@Sun.COM 	h = scf_instance_handle(inst);
9167887SLiane.Praza@Sun.COM 	if (h == NULL)
9177887SLiane.Praza@Sun.COM 		return (-1);
9187887SLiane.Praza@Sun.COM 
9197887SLiane.Praza@Sun.COM 	if ((*snap = scf_snapshot_create(h)) == NULL) {
9207887SLiane.Praza@Sun.COM 		return (-1);
9217887SLiane.Praza@Sun.COM 	}
9227887SLiane.Praza@Sun.COM 
9237887SLiane.Praza@Sun.COM 	/* Use running snapshot by default. */
9247887SLiane.Praza@Sun.COM 	if (snapshot == NULL)
9257887SLiane.Praza@Sun.COM 		err = scf_instance_get_snapshot(inst, "running", *snap);
9267887SLiane.Praza@Sun.COM 	else
9277887SLiane.Praza@Sun.COM 		err = scf_instance_get_snapshot(inst, snapshot, *snap);
9287887SLiane.Praza@Sun.COM 
9297887SLiane.Praza@Sun.COM 	if (err != 0) {
9307887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
9317887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(*snap);
9327887SLiane.Praza@Sun.COM 			*snap = NULL;
9337887SLiane.Praza@Sun.COM 			return (-1);
9347887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
9357887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
9367887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(*snap);
9377887SLiane.Praza@Sun.COM 			*snap = NULL;
9387887SLiane.Praza@Sun.COM 			return (-1);
9397887SLiane.Praza@Sun.COM 
9407887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
9417887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(*snap);
9427887SLiane.Praza@Sun.COM 			*snap = NULL;
9437887SLiane.Praza@Sun.COM 			return (0);
9447887SLiane.Praza@Sun.COM 
9457887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
9467887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
9477887SLiane.Praza@Sun.COM 		default:
9487887SLiane.Praza@Sun.COM 			assert(0);
9497887SLiane.Praza@Sun.COM 			abort();
9507887SLiane.Praza@Sun.COM 		}
9517887SLiane.Praza@Sun.COM 	}
9527887SLiane.Praza@Sun.COM 
9537887SLiane.Praza@Sun.COM 	/*
9547887SLiane.Praza@Sun.COM 	 * Explicitly set SCF_ERROR_NONE so that the SCF_ERROR_NOT_FOUND
9557887SLiane.Praza@Sun.COM 	 * return above is explicitly guaranteed to be from
9567887SLiane.Praza@Sun.COM 	 * scf_instance_get_snapshot().
9577887SLiane.Praza@Sun.COM 	 */
9587887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NONE);
9597887SLiane.Praza@Sun.COM 	return (0);
9607887SLiane.Praza@Sun.COM }
9617887SLiane.Praza@Sun.COM 
9627887SLiane.Praza@Sun.COM /*
9637887SLiane.Praza@Sun.COM  * Returns NULL on error, sets scf_error() to:
9647887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
9657887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
9667887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
9677887SLiane.Praza@Sun.COM  *     The restarter's FMRI does not match an existing instance.
9687887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
9697887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
9707887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
9717887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
9727887SLiane.Praza@Sun.COM  *     The restarter's FMRI is not a valid FMRI.
9737887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
9747887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
9757887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
9767887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
9777887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
9787887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
9797887SLiane.Praza@Sun.COM  *     restarter property is not SCF_TYPE_ASTRING or has more than one value
9807887SLiane.Praza@Sun.COM  */
9817887SLiane.Praza@Sun.COM static scf_instance_t *
_get_restarter_inst(scf_handle_t * h,scf_service_t * svc,scf_instance_t * inst,scf_snapshot_t * s)9827887SLiane.Praza@Sun.COM _get_restarter_inst(scf_handle_t *h, scf_service_t *svc,
9837887SLiane.Praza@Sun.COM     scf_instance_t *inst, scf_snapshot_t *s)
9847887SLiane.Praza@Sun.COM {
9857887SLiane.Praza@Sun.COM 	char *restarter = NULL;
9867887SLiane.Praza@Sun.COM 	scf_instance_t *ri = NULL;
9877887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
9887887SLiane.Praza@Sun.COM 	int ret = 0;
9897887SLiane.Praza@Sun.COM 
9907887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
9917887SLiane.Praza@Sun.COM 	assert(svc ==  NULL || inst == NULL);
9927887SLiane.Praza@Sun.COM 
9937887SLiane.Praza@Sun.COM 	if ((ri = scf_instance_create(h)) == NULL ||
9947887SLiane.Praza@Sun.COM 	    (pg = scf_pg_create(h)) == NULL) {
9957887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
99611750SAntonello.Cruz@Sun.COM 		goto _get_restarter_inst_fail;
9977887SLiane.Praza@Sun.COM 	}
9987887SLiane.Praza@Sun.COM 
9997887SLiane.Praza@Sun.COM 	if (inst != NULL)
10007887SLiane.Praza@Sun.COM 		ret = scf_instance_get_pg_composed(inst, s, SCF_PG_GENERAL,
10017887SLiane.Praza@Sun.COM 		    pg);
10027887SLiane.Praza@Sun.COM 	else
10037887SLiane.Praza@Sun.COM 		ret = scf_service_get_pg(svc, SCF_PG_GENERAL, pg);
10047887SLiane.Praza@Sun.COM 
10057887SLiane.Praza@Sun.COM 	if (ret != 0) {
10067887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
10077887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
10087887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
10097887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
10107887SLiane.Praza@Sun.COM 			/* Assume default restarter. */
10117887SLiane.Praza@Sun.COM 			break;
10127887SLiane.Praza@Sun.COM 
10137887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
10147887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
10157887SLiane.Praza@Sun.COM 			/*
10167887SLiane.Praza@Sun.COM 			 * If the arguments to the above functions
10177887SLiane.Praza@Sun.COM 			 * aren't derived from the same handle, there's
10187887SLiane.Praza@Sun.COM 			 * something wrong with the internal implementation,
10197887SLiane.Praza@Sun.COM 			 * not the public caller further up the chain.
10207887SLiane.Praza@Sun.COM 			 */
10217887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
10227887SLiane.Praza@Sun.COM 		default:
10237887SLiane.Praza@Sun.COM 			assert(0);
10247887SLiane.Praza@Sun.COM 			abort();
10257887SLiane.Praza@Sun.COM 		}
10267887SLiane.Praza@Sun.COM 	} else {
10277887SLiane.Praza@Sun.COM 		restarter = _scf_read_single_astring_from_pg(pg,
10287887SLiane.Praza@Sun.COM 		    SCF_PROPERTY_RESTARTER);
10297887SLiane.Praza@Sun.COM 		/* zero length string is NOT a valid restarter */
10307887SLiane.Praza@Sun.COM 		if (restarter != NULL && restarter[0] == '\0') {
10317887SLiane.Praza@Sun.COM 			free(restarter);
10327887SLiane.Praza@Sun.COM 			restarter = NULL;
10337887SLiane.Praza@Sun.COM 		} else if (restarter == NULL) {
10347887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
10357887SLiane.Praza@Sun.COM 				goto _get_restarter_inst_fail;
10367887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
10377887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
10387887SLiane.Praza@Sun.COM 				break;
10397887SLiane.Praza@Sun.COM 
10407887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
10417887SLiane.Praza@Sun.COM 			case SCF_ERROR_TYPE_MISMATCH:
10427887SLiane.Praza@Sun.COM 				(void) scf_set_error(
10437887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
10447887SLiane.Praza@Sun.COM 				goto _get_restarter_inst_fail;
10457887SLiane.Praza@Sun.COM 
10467887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
10477887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
10487887SLiane.Praza@Sun.COM 			default:
10497887SLiane.Praza@Sun.COM 				assert(0);
10507887SLiane.Praza@Sun.COM 				abort();
10517887SLiane.Praza@Sun.COM 			}
10527887SLiane.Praza@Sun.COM 		}
10537887SLiane.Praza@Sun.COM 	}
10547887SLiane.Praza@Sun.COM 
10557887SLiane.Praza@Sun.COM 	if (restarter == NULL) {
10567887SLiane.Praza@Sun.COM 		/* Use default restarter */
10577887SLiane.Praza@Sun.COM 		restarter = strdup(SCF_SERVICE_STARTD);
10587887SLiane.Praza@Sun.COM 		if (restarter == NULL) {
10597887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
10607887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
10617887SLiane.Praza@Sun.COM 		}
10627887SLiane.Praza@Sun.COM 	}
10637887SLiane.Praza@Sun.COM 
10647887SLiane.Praza@Sun.COM 	if (scf_handle_decode_fmri(h, restarter, NULL, NULL, ri, NULL, NULL,
10657887SLiane.Praza@Sun.COM 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
10667887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
10677887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
10687887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
10697887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
10707887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
10717887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
10727887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
10737887SLiane.Praza@Sun.COM 
10747887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
10757887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
10767887SLiane.Praza@Sun.COM 		default:
10777887SLiane.Praza@Sun.COM 			assert(0);
10787887SLiane.Praza@Sun.COM 			abort();
10797887SLiane.Praza@Sun.COM 		}
10807887SLiane.Praza@Sun.COM 	}
10817887SLiane.Praza@Sun.COM 	free(restarter);
10827887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
10837887SLiane.Praza@Sun.COM 
10847887SLiane.Praza@Sun.COM 	return (ri);
10857887SLiane.Praza@Sun.COM 
10867887SLiane.Praza@Sun.COM _get_restarter_inst_fail:
108711750SAntonello.Cruz@Sun.COM 	free(restarter);
10887887SLiane.Praza@Sun.COM 	scf_instance_destroy(ri);
10897887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
10907887SLiane.Praza@Sun.COM 	return (NULL);
10917887SLiane.Praza@Sun.COM }
10927887SLiane.Praza@Sun.COM 
10937887SLiane.Praza@Sun.COM /*
10947887SLiane.Praza@Sun.COM  * Returns NULL on error, sets scf_error() to:
10957887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
10967887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
10977887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
10987887SLiane.Praza@Sun.COM  *     Restarter property has more than one value associated with it,
10997887SLiane.Praza@Sun.COM  *     or FMRI does not meet restrictions in scf_handle_decode_fmri() flags.
11007887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
11017887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
11027887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
11037887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
11047887SLiane.Praza@Sun.COM  *     The fmri argument in scf_handle_decode_fmri() is not a valid FMRI.
11057887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
11067887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
11077887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
11087887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
11097887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
11107887SLiane.Praza@Sun.COM  */
11117887SLiane.Praza@Sun.COM static scf_instance_t *
_get_global_inst(scf_handle_t * h)11127887SLiane.Praza@Sun.COM _get_global_inst(scf_handle_t *h)
11137887SLiane.Praza@Sun.COM {
11147887SLiane.Praza@Sun.COM 	scf_instance_t *ri;
11157887SLiane.Praza@Sun.COM 
11167887SLiane.Praza@Sun.COM 	if ((ri = scf_instance_create(h)) == NULL) {
11177887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
11187887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_RESOURCES);
11197887SLiane.Praza@Sun.COM 		return (NULL);
11207887SLiane.Praza@Sun.COM 	}
11217887SLiane.Praza@Sun.COM 
11227887SLiane.Praza@Sun.COM 	if (scf_handle_decode_fmri(h, SCF_INSTANCE_GLOBAL, NULL, NULL, ri,
11237887SLiane.Praza@Sun.COM 	    NULL, NULL,
11247887SLiane.Praza@Sun.COM 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
11257887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
11267887SLiane.Praza@Sun.COM 			scf_instance_destroy(ri);
11277887SLiane.Praza@Sun.COM 			return (NULL);
11287887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
11297887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
11307887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
11317887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
11327887SLiane.Praza@Sun.COM 			scf_instance_destroy(ri);
11337887SLiane.Praza@Sun.COM 			return (NULL);
11347887SLiane.Praza@Sun.COM 
11357887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
11367887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
11377887SLiane.Praza@Sun.COM 		default:
11387887SLiane.Praza@Sun.COM 			assert(0);
11397887SLiane.Praza@Sun.COM 			abort();
11407887SLiane.Praza@Sun.COM 		}
11417887SLiane.Praza@Sun.COM 	}
11427887SLiane.Praza@Sun.COM 
11437887SLiane.Praza@Sun.COM 	return (ri);
11447887SLiane.Praza@Sun.COM }
11457887SLiane.Praza@Sun.COM 
11467887SLiane.Praza@Sun.COM /*
11477887SLiane.Praza@Sun.COM  * Call the supplied function for each of the service or instance, the
11487887SLiane.Praza@Sun.COM  * service's restarter, and the globally defined template instance.
11497887SLiane.Praza@Sun.COM  * If the function returns SCF_WALK_ERROR, the walk is ended.  If
11507887SLiane.Praza@Sun.COM  * the function returns SCF_WALK_NEXT, the next entity is tried.
11517887SLiane.Praza@Sun.COM  *
11527887SLiane.Praza@Sun.COM  * The function is only expected to return SCF_WALK_DONE if it has
11537887SLiane.Praza@Sun.COM  * found a property group match in the current entity, and has
11547887SLiane.Praza@Sun.COM  * populated p->pw_pg with the matching property group.
115511750SAntonello.Cruz@Sun.COM  *
115611750SAntonello.Cruz@Sun.COM  * The caller of _walk_template_instances() MUST check if the passed parameters
115711750SAntonello.Cruz@Sun.COM  * inst and svc match the fields pw_inst and pw_svc in the resulting
115811750SAntonello.Cruz@Sun.COM  * pg_tmpl_walk_t and call the destructor for the unmatching objects. The walker
115911750SAntonello.Cruz@Sun.COM  * may silently drop them if the template definition is in the restarter or in
116011750SAntonello.Cruz@Sun.COM  * the global instance.
11617887SLiane.Praza@Sun.COM  */
11627887SLiane.Praza@Sun.COM static void
_walk_template_instances(scf_service_t * svc,scf_instance_t * inst,scf_snapshot_t * snap,walk_template_inst_func_t * func,pg_tmpl_walk_t * p,int flag)11637887SLiane.Praza@Sun.COM _walk_template_instances(scf_service_t *svc, scf_instance_t *inst,
11647887SLiane.Praza@Sun.COM     scf_snapshot_t *snap, walk_template_inst_func_t *func,
11657887SLiane.Praza@Sun.COM     pg_tmpl_walk_t *p, int flag)
11667887SLiane.Praza@Sun.COM {
11677887SLiane.Praza@Sun.COM 	scf_instance_t *tmpl_inst = NULL;
11687887SLiane.Praza@Sun.COM 	scf_handle_t *h;
11697887SLiane.Praza@Sun.COM 	int ret;
11707887SLiane.Praza@Sun.COM 	char *tg = NULL;
11717887SLiane.Praza@Sun.COM 
11727887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
11737887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
11747887SLiane.Praza@Sun.COM 
11757887SLiane.Praza@Sun.COM 	if (inst != NULL)
11767887SLiane.Praza@Sun.COM 		h = scf_instance_handle(inst);
11777887SLiane.Praza@Sun.COM 	else
11787887SLiane.Praza@Sun.COM 		h = scf_service_handle(svc);
11797887SLiane.Praza@Sun.COM 	if (h == NULL)
11807887SLiane.Praza@Sun.COM 		goto done;
11817887SLiane.Praza@Sun.COM 
11827887SLiane.Praza@Sun.COM 	/* First, use supplied service or instance */
11837887SLiane.Praza@Sun.COM 	p->pw_target = SCF_TM_TARGET_THIS;
11847887SLiane.Praza@Sun.COM 	ret = func(svc, inst, p);
11857887SLiane.Praza@Sun.COM 	switch (ret) {
11867887SLiane.Praza@Sun.COM 	case SCF_WALK_NEXT:
11877887SLiane.Praza@Sun.COM 		break;
11887887SLiane.Praza@Sun.COM 	case SCF_WALK_DONE:
11897887SLiane.Praza@Sun.COM 		/*
11907887SLiane.Praza@Sun.COM 		 * Check that the template scoping matches and if not,
11917887SLiane.Praza@Sun.COM 		 * continue.
11927887SLiane.Praza@Sun.COM 		 */
11937887SLiane.Praza@Sun.COM 		assert(p->pw_pg != NULL);
11947887SLiane.Praza@Sun.COM 		tg = _scf_read_single_astring_from_pg(p->pw_pg,
11957887SLiane.Praza@Sun.COM 		    SCF_PROPERTY_TM_TARGET);
11967887SLiane.Praza@Sun.COM 		if (tg == NULL || /* scf_error() was set */
11977887SLiane.Praza@Sun.COM 		    (strcmp(tg, SCF_TM_TARGET_INSTANCE) != 0 &&
11987887SLiane.Praza@Sun.COM 		    strcmp(tg, SCF_TM_TARGET_THIS) != 0 &&
11997887SLiane.Praza@Sun.COM 		    (flag & SCF_PG_TMPL_FLAG_EXACT) !=
12007887SLiane.Praza@Sun.COM 		    SCF_PG_TMPL_FLAG_EXACT)) {
12017887SLiane.Praza@Sun.COM 			scf_pg_destroy(p->pw_pg);
12027887SLiane.Praza@Sun.COM 			p->pw_pg = NULL;
12037887SLiane.Praza@Sun.COM 			if (tg != NULL) {
12047887SLiane.Praza@Sun.COM 				free(tg);
12057887SLiane.Praza@Sun.COM 				tg = NULL;
12067887SLiane.Praza@Sun.COM 				break;
12077887SLiane.Praza@Sun.COM 			}
12087887SLiane.Praza@Sun.COM 		}
12097887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
12107887SLiane.Praza@Sun.COM 	case SCF_WALK_ERROR:
12117887SLiane.Praza@Sun.COM 		goto done;
12127887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
12137887SLiane.Praza@Sun.COM 	default:
12147887SLiane.Praza@Sun.COM 		assert(0);
12157887SLiane.Praza@Sun.COM 		abort();
12167887SLiane.Praza@Sun.COM 	}
12177887SLiane.Praza@Sun.COM 
12187887SLiane.Praza@Sun.COM 	/* Next the restarter. */
12197887SLiane.Praza@Sun.COM 	p->pw_target = SCF_TM_TARGET_DELEGATE;
12207887SLiane.Praza@Sun.COM 	tmpl_inst = _get_restarter_inst(h, svc, inst, snap);
12217887SLiane.Praza@Sun.COM 	if (tmpl_inst != NULL) {
12227887SLiane.Praza@Sun.COM 		ret = func(NULL, tmpl_inst, p);
12237887SLiane.Praza@Sun.COM 		switch (ret) {
12247887SLiane.Praza@Sun.COM 		case SCF_WALK_NEXT:
12257887SLiane.Praza@Sun.COM 			break;
12267887SLiane.Praza@Sun.COM 		case SCF_WALK_DONE:
12277887SLiane.Praza@Sun.COM 			/*
12287887SLiane.Praza@Sun.COM 			 * Check that the template scoping matches and if not,
12297887SLiane.Praza@Sun.COM 			 * continue.
12307887SLiane.Praza@Sun.COM 			 */
12317887SLiane.Praza@Sun.COM 			assert(p->pw_pg != NULL);
12327887SLiane.Praza@Sun.COM 			tg = _scf_read_single_astring_from_pg(p->pw_pg,
12337887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_TARGET);
12347887SLiane.Praza@Sun.COM 			if (tg == NULL || /* scf_error() was set */
12357887SLiane.Praza@Sun.COM 			    strcmp(tg, SCF_TM_TARGET_DELEGATE) != 0) {
12367887SLiane.Praza@Sun.COM 				scf_pg_destroy(p->pw_pg);
12377887SLiane.Praza@Sun.COM 				p->pw_pg = NULL;
12387887SLiane.Praza@Sun.COM 				if (tg != NULL) {
12397887SLiane.Praza@Sun.COM 					free(tg);
12407887SLiane.Praza@Sun.COM 					tg = NULL;
12417887SLiane.Praza@Sun.COM 					break;
12427887SLiane.Praza@Sun.COM 				}
12437887SLiane.Praza@Sun.COM 			}
12447887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
12457887SLiane.Praza@Sun.COM 		case SCF_WALK_ERROR:
12467887SLiane.Praza@Sun.COM 			goto done;
12477887SLiane.Praza@Sun.COM 			/*NOTREACHED*/
12487887SLiane.Praza@Sun.COM 		default:
12497887SLiane.Praza@Sun.COM 			assert(0);
12507887SLiane.Praza@Sun.COM 			abort();
12517887SLiane.Praza@Sun.COM 		}
12527887SLiane.Praza@Sun.COM 	}
12537887SLiane.Praza@Sun.COM 
12547887SLiane.Praza@Sun.COM 	p->pw_target = SCF_TM_TARGET_ALL;
12557887SLiane.Praza@Sun.COM 	scf_instance_destroy(tmpl_inst);
12567887SLiane.Praza@Sun.COM 	tmpl_inst = _get_global_inst(h);
12577887SLiane.Praza@Sun.COM 	if (tmpl_inst != NULL) {
12587887SLiane.Praza@Sun.COM 		ret = func(NULL, tmpl_inst, p);
12597887SLiane.Praza@Sun.COM 		switch (ret) {
12607887SLiane.Praza@Sun.COM 		case SCF_WALK_NEXT:
12617887SLiane.Praza@Sun.COM 			break;
12627887SLiane.Praza@Sun.COM 		case SCF_WALK_DONE:
12637887SLiane.Praza@Sun.COM 			/*
12647887SLiane.Praza@Sun.COM 			 * Check that the template scoping matches and if not,
12657887SLiane.Praza@Sun.COM 			 * continue.
12667887SLiane.Praza@Sun.COM 			 */
12677887SLiane.Praza@Sun.COM 			assert(p->pw_pg != NULL);
12687887SLiane.Praza@Sun.COM 			tg = _scf_read_single_astring_from_pg(p->pw_pg,
12697887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_TARGET);
12707887SLiane.Praza@Sun.COM 			if (tg == NULL || /* scf_error() was set */
12717887SLiane.Praza@Sun.COM 			    strcmp(tg, SCF_TM_TARGET_ALL) != 0) {
12727887SLiane.Praza@Sun.COM 				scf_pg_destroy(p->pw_pg);
12737887SLiane.Praza@Sun.COM 				p->pw_pg = NULL;
12747887SLiane.Praza@Sun.COM 				if (tg != NULL) {
12757887SLiane.Praza@Sun.COM 					free(tg);
12767887SLiane.Praza@Sun.COM 					tg = NULL;
12777887SLiane.Praza@Sun.COM 					break;
12787887SLiane.Praza@Sun.COM 				}
12797887SLiane.Praza@Sun.COM 			}
12807887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
12817887SLiane.Praza@Sun.COM 		case SCF_WALK_ERROR:
12827887SLiane.Praza@Sun.COM 			goto done;
12837887SLiane.Praza@Sun.COM 			/*NOTREACHED*/
12847887SLiane.Praza@Sun.COM 		default:
12857887SLiane.Praza@Sun.COM 			assert(0);
12867887SLiane.Praza@Sun.COM 			abort();
12877887SLiane.Praza@Sun.COM 		}
12887887SLiane.Praza@Sun.COM 	}
12897887SLiane.Praza@Sun.COM 
12907887SLiane.Praza@Sun.COM done:
12917887SLiane.Praza@Sun.COM 	free(tg);
12927887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_DONE)
12937887SLiane.Praza@Sun.COM 		scf_instance_destroy(tmpl_inst);
12947887SLiane.Praza@Sun.COM 	p->pw_target = NULL;
12957887SLiane.Praza@Sun.COM }
12967887SLiane.Praza@Sun.COM 
12977887SLiane.Praza@Sun.COM /*
12987887SLiane.Praza@Sun.COM  * _get_pg() returns 0 on success and -1 on failure.  Sets scf_error()
12997887SLiane.Praza@Sun.COM  * on failure.
13007887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
13017887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
13027887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
13037887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_MISMATCH
13047887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
13057887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
13067887SLiane.Praza@Sun.COM  *     name is not a valid property group.
13077887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
13087887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
13097887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
13107887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
13117887SLiane.Praza@Sun.COM  */
13127887SLiane.Praza@Sun.COM static int
_get_pg(scf_service_t * svc,scf_instance_t * inst,const scf_snapshot_t * snap,const char * name,scf_propertygroup_t * pg)13137887SLiane.Praza@Sun.COM _get_pg(scf_service_t *svc, scf_instance_t *inst,
13147887SLiane.Praza@Sun.COM     const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg)
13157887SLiane.Praza@Sun.COM {
13167887SLiane.Praza@Sun.COM 	int ret;
13177887SLiane.Praza@Sun.COM 
13187887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
13197887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
13207887SLiane.Praza@Sun.COM 	assert(pg != NULL);
13217887SLiane.Praza@Sun.COM 
13227887SLiane.Praza@Sun.COM 	if (inst != NULL)
13237887SLiane.Praza@Sun.COM 		ret = scf_instance_get_pg_composed(inst, snap, name, pg);
13247887SLiane.Praza@Sun.COM 	else
13257887SLiane.Praza@Sun.COM 		ret = scf_service_get_pg(svc, name, pg);
13267887SLiane.Praza@Sun.COM 
13277887SLiane.Praza@Sun.COM 	return (ret);
13287887SLiane.Praza@Sun.COM }
13297887SLiane.Praza@Sun.COM 
13307887SLiane.Praza@Sun.COM /*
13317887SLiane.Praza@Sun.COM  * Returns SCF_WALK_NEXT for not found, SCF_WALK_ERROR for error,
13327887SLiane.Praza@Sun.COM  * and SCF_WALK_DONE for found.
13337887SLiane.Praza@Sun.COM  * On error, destroy pg and set it to NULL.
13347887SLiane.Praza@Sun.COM  *
13357887SLiane.Praza@Sun.COM  * Sets scf_error() if SCF_WALK_ERROR is returned to _BACKEND_ACCESS,
13367887SLiane.Praza@Sun.COM  * _CONNECTION_BROKEN, _INTERNAL, _INVALID_ARGUMENT (name is not a
13377887SLiane.Praza@Sun.COM  *  valid property group), _NO_RESOURCES, or _NOT_BOUND.
13387887SLiane.Praza@Sun.COM  */
13397887SLiane.Praza@Sun.COM static int
_lookup_pg(scf_service_t * svc,scf_instance_t * inst,const scf_snapshot_t * snap,const char * name,scf_propertygroup_t * pg)13407887SLiane.Praza@Sun.COM _lookup_pg(scf_service_t *svc, scf_instance_t *inst,
13417887SLiane.Praza@Sun.COM     const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg)
13427887SLiane.Praza@Sun.COM {
13437887SLiane.Praza@Sun.COM 	int ret;
13447887SLiane.Praza@Sun.COM 
13457887SLiane.Praza@Sun.COM 	ret = _get_pg(svc, inst, snap, name, pg);
13467887SLiane.Praza@Sun.COM 
13477887SLiane.Praza@Sun.COM 	if (ret == 0) {
13487887SLiane.Praza@Sun.COM 		return (SCF_WALK_DONE);
13497887SLiane.Praza@Sun.COM 	} else {
13507887SLiane.Praza@Sun.COM 		switch (scf_error()) {
13517887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
13527887SLiane.Praza@Sun.COM 		case SCF_ERROR_DELETED:
13537887SLiane.Praza@Sun.COM 			return (SCF_WALK_NEXT);
13547887SLiane.Praza@Sun.COM 
13557887SLiane.Praza@Sun.COM 		case SCF_ERROR_BACKEND_ACCESS:
13567887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONNECTION_BROKEN:
13577887SLiane.Praza@Sun.COM 		case SCF_ERROR_INTERNAL:
13587887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
13597887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_BOUND:
13607887SLiane.Praza@Sun.COM 		case SCF_ERROR_NO_RESOURCES:
13617887SLiane.Praza@Sun.COM 			scf_pg_destroy(pg);
13627887SLiane.Praza@Sun.COM 			pg = NULL;
13637887SLiane.Praza@Sun.COM 			return (SCF_WALK_ERROR);
13647887SLiane.Praza@Sun.COM 
13657887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
13667887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
13677887SLiane.Praza@Sun.COM 		default:
13687887SLiane.Praza@Sun.COM 			assert(0);
13697887SLiane.Praza@Sun.COM 			abort();
13707887SLiane.Praza@Sun.COM 		}
13717887SLiane.Praza@Sun.COM 	}
13727887SLiane.Praza@Sun.COM 
13737887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
13747887SLiane.Praza@Sun.COM }
13757887SLiane.Praza@Sun.COM 
13767887SLiane.Praza@Sun.COM /*
13777887SLiane.Praza@Sun.COM  * If match, return 0.  If no match, return 1.  If error, return -1.
13787887SLiane.Praza@Sun.COM  * On error set scf_error() to _BACKEND_ACCESS, _CONNECTION_BROKEN,
13797887SLiane.Praza@Sun.COM  * _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, _NO_RESOURCES, _NOT_BOUND,
13807887SLiane.Praza@Sun.COM  * _NOT_SET (property group specified by pg is not set), _PERMISSION_DENIED,
13817887SLiane.Praza@Sun.COM  * or _TEMPLATE_INVALID (target property is not SCF_TYPE_ASTRING or has
13827887SLiane.Praza@Sun.COM  * more than one value).
13837887SLiane.Praza@Sun.COM  */
13847887SLiane.Praza@Sun.COM static int
check_target_match(scf_propertygroup_t * pg,const char * target)13857887SLiane.Praza@Sun.COM check_target_match(scf_propertygroup_t *pg, const char *target)
13867887SLiane.Praza@Sun.COM {
13877887SLiane.Praza@Sun.COM 	char *pg_target;
13887887SLiane.Praza@Sun.COM 	int ret = 0;
13897887SLiane.Praza@Sun.COM 
13907887SLiane.Praza@Sun.COM 	pg_target = _scf_read_single_astring_from_pg(pg,
13917887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TARGET);
13927887SLiane.Praza@Sun.COM 	if (pg_target == NULL) {
13937887SLiane.Praza@Sun.COM 		switch (scf_error()) {
13947887SLiane.Praza@Sun.COM 		case SCF_ERROR_DELETED:
13957887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
13967887SLiane.Praza@Sun.COM 			return (1);
13977887SLiane.Praza@Sun.COM 
13987887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
13997887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
14007887SLiane.Praza@Sun.COM 			(void) scf_set_error(
14017887SLiane.Praza@Sun.COM 			    SCF_ERROR_TEMPLATE_INVALID);
14027887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
14037887SLiane.Praza@Sun.COM 
14047887SLiane.Praza@Sun.COM 		case SCF_ERROR_BACKEND_ACCESS:
14057887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONNECTION_BROKEN:
14067887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_DESTROYED:
14077887SLiane.Praza@Sun.COM 		case SCF_ERROR_INTERNAL:
14087887SLiane.Praza@Sun.COM 		case SCF_ERROR_NO_RESOURCES:
14097887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_BOUND:
14107887SLiane.Praza@Sun.COM 		case SCF_ERROR_PERMISSION_DENIED:
14117887SLiane.Praza@Sun.COM 			return (-1);
14127887SLiane.Praza@Sun.COM 
14137887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
14147887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
14157887SLiane.Praza@Sun.COM 		default:
14167887SLiane.Praza@Sun.COM 			assert(0);
14177887SLiane.Praza@Sun.COM 			abort();
14187887SLiane.Praza@Sun.COM 		}
14197887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
14207887SLiane.Praza@Sun.COM 	}
14217887SLiane.Praza@Sun.COM 
14227887SLiane.Praza@Sun.COM 	/* For a desired target of 'this', check for 'this' and 'instance'. */
14237887SLiane.Praza@Sun.COM 	if ((strcmp(target, SCF_TM_TARGET_INSTANCE) == 0 ||
14247887SLiane.Praza@Sun.COM 	    strcmp(target, SCF_TM_TARGET_THIS) == 0) &&
14257887SLiane.Praza@Sun.COM 	    (strcmp(pg_target, SCF_TM_TARGET_INSTANCE) == 0 ||
14267887SLiane.Praza@Sun.COM 	    strcmp(pg_target, SCF_TM_TARGET_THIS) == 0)) {
14277887SLiane.Praza@Sun.COM 		goto cleanup;
14287887SLiane.Praza@Sun.COM 	}
14297887SLiane.Praza@Sun.COM 
14307887SLiane.Praza@Sun.COM 	if (strcmp(target, SCF_TM_TARGET_DELEGATE) == 0 &&
14317887SLiane.Praza@Sun.COM 	    strcmp(pg_target, SCF_TM_TARGET_DELEGATE) == 0) {
14327887SLiane.Praza@Sun.COM 		goto cleanup;
14337887SLiane.Praza@Sun.COM 	}
14347887SLiane.Praza@Sun.COM 
14357887SLiane.Praza@Sun.COM 	if (strcmp(target, SCF_TM_TARGET_ALL) == 0 &&
14367887SLiane.Praza@Sun.COM 	    strcmp(pg_target, SCF_TM_TARGET_ALL) == 0) {
14377887SLiane.Praza@Sun.COM 		goto cleanup;
14387887SLiane.Praza@Sun.COM 	}
14397887SLiane.Praza@Sun.COM 
14407887SLiane.Praza@Sun.COM 	ret = 1;
14417887SLiane.Praza@Sun.COM cleanup:
14427887SLiane.Praza@Sun.COM 	free(pg_target);
14437887SLiane.Praza@Sun.COM 	return (ret);
14447887SLiane.Praza@Sun.COM }
14457887SLiane.Praza@Sun.COM 
14467887SLiane.Praza@Sun.COM /*
14477887SLiane.Praza@Sun.COM  * Check if a matching template property group exists for each of:
14487887SLiane.Praza@Sun.COM  * name and type, name only, type only, and completely wildcarded
14497887SLiane.Praza@Sun.COM  * template.
14507887SLiane.Praza@Sun.COM  *
14517887SLiane.Praza@Sun.COM  * Both pg_name and pg_type are optional.
14527887SLiane.Praza@Sun.COM  *
14537887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error():
14547887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
14557887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
14567887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
14577887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
14587887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
14597887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
14607887SLiane.Praza@Sun.COM  *     can't combine the _tmpl_pg_name arguments and get a reasonable
14617887SLiane.Praza@Sun.COM  *     length name, or pg_name is not a valid property group.
14627887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
14637887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
14647887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
14657887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
14667887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
14677887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
14687887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
14697887SLiane.Praza@Sun.COM  *     target property is not SCF_TYPE_ASTRING or has more than one value.
14707887SLiane.Praza@Sun.COM  */
14717887SLiane.Praza@Sun.COM static scf_propertygroup_t *
_find_template_pg_match(scf_service_t * svc,scf_instance_t * inst,const scf_snapshot_t * snap,const char * pg_name,const char * pg_type,const char * target,char ** tmpl_pg_name)14727887SLiane.Praza@Sun.COM _find_template_pg_match(scf_service_t *svc, scf_instance_t *inst,
14737887SLiane.Praza@Sun.COM     const scf_snapshot_t *snap, const char *pg_name, const char *pg_type,
14747887SLiane.Praza@Sun.COM     const char *target, char **tmpl_pg_name)
14757887SLiane.Praza@Sun.COM {
14767887SLiane.Praza@Sun.COM 	int ret, r;
14777887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
14787887SLiane.Praza@Sun.COM 	scf_handle_t *h;
14797887SLiane.Praza@Sun.COM 	scf_iter_t *iter;
14807887SLiane.Praza@Sun.COM 	char *name, *type;
14817887SLiane.Praza@Sun.COM 
14827887SLiane.Praza@Sun.COM 	assert(inst != NULL || svc != NULL);
14837887SLiane.Praza@Sun.COM 	assert(inst == NULL || svc == NULL);
14847887SLiane.Praza@Sun.COM 
14857887SLiane.Praza@Sun.COM 	if (inst != NULL)
14867887SLiane.Praza@Sun.COM 		h = scf_instance_handle(inst);
14877887SLiane.Praza@Sun.COM 	else
14887887SLiane.Praza@Sun.COM 		h = scf_service_handle(svc);
14897887SLiane.Praza@Sun.COM 	if (h == NULL) {
14907887SLiane.Praza@Sun.COM 		return (NULL);
14917887SLiane.Praza@Sun.COM 	}
14927887SLiane.Praza@Sun.COM 
14937887SLiane.Praza@Sun.COM 	if ((pg = scf_pg_create(h)) == NULL ||
14947887SLiane.Praza@Sun.COM 	    (iter = scf_iter_create(h)) == NULL) {
14957887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
14967887SLiane.Praza@Sun.COM 		scf_pg_destroy(pg);
14977887SLiane.Praza@Sun.COM 		return (NULL);
14987887SLiane.Praza@Sun.COM 	}
14997887SLiane.Praza@Sun.COM 
15007887SLiane.Praza@Sun.COM 	/*
15017887SLiane.Praza@Sun.COM 	 * We're going to walk through the possible pg templates that
15027887SLiane.Praza@Sun.COM 	 * could match the supplied name and type.  We do this
15037887SLiane.Praza@Sun.COM 	 * by explicit name lookups when possible to avoid having to
15047887SLiane.Praza@Sun.COM 	 * keep track of a most-explicit-match during iteration.
15057887SLiane.Praza@Sun.COM 	 */
15067887SLiane.Praza@Sun.COM 
15077887SLiane.Praza@Sun.COM 	/* First look for a template with name and type set and matching. */
15087887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(pg_name, pg_type, 1);
15097887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
15107887SLiane.Praza@Sun.COM 		goto fail;
15117887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
15127887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
15137887SLiane.Praza@Sun.COM 		if (pg != NULL) {
15147887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
15157887SLiane.Praza@Sun.COM 				goto done;
15167887SLiane.Praza@Sun.COM 			else if (r == -1)
15177887SLiane.Praza@Sun.COM 				goto fail;
15187887SLiane.Praza@Sun.COM 		} else {
15197887SLiane.Praza@Sun.COM 			goto done;
15207887SLiane.Praza@Sun.COM 		}
15217887SLiane.Praza@Sun.COM 	}
15227887SLiane.Praza@Sun.COM 	free(*tmpl_pg_name);
15237887SLiane.Praza@Sun.COM 
15247887SLiane.Praza@Sun.COM 	/*
15257887SLiane.Praza@Sun.COM 	 * Need to search on a name-only match before searching on
15267887SLiane.Praza@Sun.COM 	 * type matches.
15277887SLiane.Praza@Sun.COM 	 */
15287887SLiane.Praza@Sun.COM 
15297887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(pg_name, NULL, 0);
15307887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
15317887SLiane.Praza@Sun.COM 		goto fail;
15327887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
15337887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
15347887SLiane.Praza@Sun.COM 		if (pg != NULL) {
15357887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
15367887SLiane.Praza@Sun.COM 				goto done;
15377887SLiane.Praza@Sun.COM 			else if (r == -1)
15387887SLiane.Praza@Sun.COM 				goto fail;
15397887SLiane.Praza@Sun.COM 		} else {
15407887SLiane.Praza@Sun.COM 			goto done;
15417887SLiane.Praza@Sun.COM 		}
15427887SLiane.Praza@Sun.COM 	}
15437887SLiane.Praza@Sun.COM 	free(*tmpl_pg_name);
15447887SLiane.Praza@Sun.COM 
15457887SLiane.Praza@Sun.COM 	/* Next, see if there's an "nt" template where the type matches. */
15467887SLiane.Praza@Sun.COM 	if (pg_type != NULL && pg_name == NULL) {
15477887SLiane.Praza@Sun.COM 		if (inst != NULL)
15487887SLiane.Praza@Sun.COM 			ret = scf_iter_instance_pgs_typed_composed(iter, inst,
15497887SLiane.Praza@Sun.COM 			    snap, SCF_GROUP_TEMPLATE_PG_PATTERN);
15507887SLiane.Praza@Sun.COM 		else
15517887SLiane.Praza@Sun.COM 			ret = scf_iter_service_pgs_typed(iter, svc,
15527887SLiane.Praza@Sun.COM 			    SCF_GROUP_TEMPLATE_PG_PATTERN);
15537887SLiane.Praza@Sun.COM 
15547887SLiane.Praza@Sun.COM 		if (ret != 0) {
15557887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
15567887SLiane.Praza@Sun.COM 				goto fail;
15577887SLiane.Praza@Sun.COM 			} else {
15587887SLiane.Praza@Sun.COM 				assert(0);
15597887SLiane.Praza@Sun.COM 				abort();
15607887SLiane.Praza@Sun.COM 			}
15617887SLiane.Praza@Sun.COM 		}
15627887SLiane.Praza@Sun.COM 
15637887SLiane.Praza@Sun.COM 		while ((ret = scf_iter_next_pg(iter, pg)) == 1) {
15647887SLiane.Praza@Sun.COM 			/* Make sure this is a name and type specified pg. */
15657887SLiane.Praza@Sun.COM 			name = _scf_read_single_astring_from_pg(pg,
15667887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_NAME);
15677887SLiane.Praza@Sun.COM 			if (name == NULL)
15687887SLiane.Praza@Sun.COM 				continue;
15697887SLiane.Praza@Sun.COM 			type = _scf_read_single_astring_from_pg(pg,
15707887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_TYPE);
15717887SLiane.Praza@Sun.COM 			if (type == NULL) {
15727887SLiane.Praza@Sun.COM 				free(name);
15737887SLiane.Praza@Sun.COM 				continue;
15747887SLiane.Praza@Sun.COM 			}
15757887SLiane.Praza@Sun.COM 			if (strcmp(pg_type, type) == 0 &&
15767887SLiane.Praza@Sun.COM 			    check_target_match(pg, target) == 0) {
15777887SLiane.Praza@Sun.COM 				*tmpl_pg_name = name;
15787887SLiane.Praza@Sun.COM 				free(type);
15797887SLiane.Praza@Sun.COM 				goto done;
15807887SLiane.Praza@Sun.COM 			}
15817887SLiane.Praza@Sun.COM 			free(type);
15827887SLiane.Praza@Sun.COM 			free(name);
15837887SLiane.Praza@Sun.COM 		}
15847887SLiane.Praza@Sun.COM 		if (ret == -1) {
15857887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
15867887SLiane.Praza@Sun.COM 				goto fail;
15877887SLiane.Praza@Sun.COM 			} else {
15887887SLiane.Praza@Sun.COM 				assert(0);
15897887SLiane.Praza@Sun.COM 				abort();
15907887SLiane.Praza@Sun.COM 			}
15917887SLiane.Praza@Sun.COM 		}
15927887SLiane.Praza@Sun.COM 	}
15937887SLiane.Praza@Sun.COM 
15947887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(NULL, pg_type, 0);
15957887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
15967887SLiane.Praza@Sun.COM 		goto fail;
15977887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
15987887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
15997887SLiane.Praza@Sun.COM 		if (pg != NULL) {
16007887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
16017887SLiane.Praza@Sun.COM 				goto done;
16027887SLiane.Praza@Sun.COM 			else if (r == -1)
16037887SLiane.Praza@Sun.COM 				goto fail;
16047887SLiane.Praza@Sun.COM 		} else {
16057887SLiane.Praza@Sun.COM 			goto done;
16067887SLiane.Praza@Sun.COM 		}
16077887SLiane.Praza@Sun.COM 	}
16087887SLiane.Praza@Sun.COM 	free(*tmpl_pg_name);
16097887SLiane.Praza@Sun.COM 
16107887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(NULL, NULL, 0);
16117887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
16127887SLiane.Praza@Sun.COM 		goto fail;
16137887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
16147887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
16157887SLiane.Praza@Sun.COM 		if (pg != NULL) {
16167887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
16177887SLiane.Praza@Sun.COM 				goto done;
16187887SLiane.Praza@Sun.COM 			else if (r == -1)
16197887SLiane.Praza@Sun.COM 				goto fail;
16207887SLiane.Praza@Sun.COM 		} else {
16217887SLiane.Praza@Sun.COM 			goto done;
16227887SLiane.Praza@Sun.COM 		}
16237887SLiane.Praza@Sun.COM 	}
16247887SLiane.Praza@Sun.COM 
16257887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NOT_FOUND);
16267887SLiane.Praza@Sun.COM fail:
16277887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
16287887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name != NULL)
16297887SLiane.Praza@Sun.COM 		free(*tmpl_pg_name);
16307887SLiane.Praza@Sun.COM 	*tmpl_pg_name = NULL;
16317887SLiane.Praza@Sun.COM 	pg = NULL;
16327887SLiane.Praza@Sun.COM done:
16337887SLiane.Praza@Sun.COM 	if (ret == SCF_WALK_ERROR)
16347887SLiane.Praza@Sun.COM 		free(*tmpl_pg_name);
16357887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
16367887SLiane.Praza@Sun.COM 	return (pg);
16377887SLiane.Praza@Sun.COM }
16387887SLiane.Praza@Sun.COM 
16397887SLiane.Praza@Sun.COM /*
16407887SLiane.Praza@Sun.COM  * Finds the pg match in either the supplied service or instance.
16417887SLiane.Praza@Sun.COM  * Returns SCF_WALK_ERROR, SCF_WALK_NEXT, or SCF_WALK_DONE.
16427887SLiane.Praza@Sun.COM  * If returning SCF_WALK_ERROR, sets scf_error():
16437887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
16447887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
16457887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
16467887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
16477887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
16487887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
16497887SLiane.Praza@Sun.COM  *     The snaphot is not a valid snapshot name,
16507887SLiane.Praza@Sun.COM  *     or can't create a reasonable property group template name.
16517887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
16527887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
16537887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
16547887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
16557887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
16567887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
16577887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
16587887SLiane.Praza@Sun.COM  *     target property is not SCF_TYPE_ASTRING or has more than one value.
16597887SLiane.Praza@Sun.COM  */
16607887SLiane.Praza@Sun.COM static int
find_pg_match(scf_service_t * svc,scf_instance_t * inst,pg_tmpl_walk_t * p)16617887SLiane.Praza@Sun.COM find_pg_match(scf_service_t *svc, scf_instance_t *inst, pg_tmpl_walk_t *p)
16627887SLiane.Praza@Sun.COM {
16637887SLiane.Praza@Sun.COM 	scf_snapshot_t *tmpl_snap = NULL;
16647887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg;
16657887SLiane.Praza@Sun.COM 	scf_handle_t *h;
16667887SLiane.Praza@Sun.COM 	char *tmpl_pg_name;
16677887SLiane.Praza@Sun.COM 
16687887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
16697887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
16707887SLiane.Praza@Sun.COM 
16717887SLiane.Praza@Sun.COM 	if (inst != NULL)
16727887SLiane.Praza@Sun.COM 		h = scf_instance_handle(inst);
16737887SLiane.Praza@Sun.COM 	else
16747887SLiane.Praza@Sun.COM 		h = scf_service_handle(svc);
16757887SLiane.Praza@Sun.COM 	if (h == NULL)
16767887SLiane.Praza@Sun.COM 		return (SCF_WALK_ERROR);
16777887SLiane.Praza@Sun.COM 
16787887SLiane.Praza@Sun.COM 	if (p->pw_snapname != NULL) {
16797887SLiane.Praza@Sun.COM 		if (_get_snapshot(inst, p->pw_snapname, &tmpl_snap) == -1)
16807887SLiane.Praza@Sun.COM 			return (SCF_WALK_ERROR);
16817887SLiane.Praza@Sun.COM 	}
16827887SLiane.Praza@Sun.COM 	pg = _find_template_pg_match(svc, inst, tmpl_snap, p->pw_pgname,
16837887SLiane.Praza@Sun.COM 	    p->pw_pgtype, p->pw_target, &tmpl_pg_name);
16847887SLiane.Praza@Sun.COM 
16857887SLiane.Praza@Sun.COM 	if (pg != NULL) {
16867887SLiane.Praza@Sun.COM 		p->pw_snap = tmpl_snap;
16877887SLiane.Praza@Sun.COM 		p->pw_pg = pg;
16887887SLiane.Praza@Sun.COM 		p->pw_tmpl_pgname = tmpl_pg_name;
16897887SLiane.Praza@Sun.COM 		p->pw_inst = inst;
16907887SLiane.Praza@Sun.COM 		p->pw_svc = svc;
16917887SLiane.Praza@Sun.COM 		return (SCF_WALK_DONE);
16927887SLiane.Praza@Sun.COM 	}
16937887SLiane.Praza@Sun.COM 
16947887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(tmpl_snap);
16957887SLiane.Praza@Sun.COM 	return (SCF_WALK_NEXT);
16967887SLiane.Praza@Sun.COM }
16977887SLiane.Praza@Sun.COM 
16987887SLiane.Praza@Sun.COM /*
16997887SLiane.Praza@Sun.COM  * return 0 on success and -1 on failure.
17007887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
17017887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
17027887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
17037887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_MISMATCH
17047887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
17057887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
17067887SLiane.Praza@Sun.COM  *     FMRI argument, snapshot name, pg_name, or pg is invalid.
17077887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
17087887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
17097887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
17107887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
17117887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
17127887SLiane.Praza@Sun.COM  */
17137887SLiane.Praza@Sun.COM int
scf_tmpl_get_by_pg(scf_propertygroup_t * pg,scf_pg_tmpl_t * pg_tmpl,int flags)17147887SLiane.Praza@Sun.COM scf_tmpl_get_by_pg(scf_propertygroup_t *pg, scf_pg_tmpl_t *pg_tmpl, int flags)
17157887SLiane.Praza@Sun.COM {
17167887SLiane.Praza@Sun.COM 	char *fmribuf = NULL, *snapbuf = NULL, *pg_name = NULL, *pg_type = NULL;
171711750SAntonello.Cruz@Sun.COM 	int ret;
17187887SLiane.Praza@Sun.COM 	ssize_t fbufsz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1;
17197887SLiane.Praza@Sun.COM 	ssize_t nbufsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
17207887SLiane.Praza@Sun.COM 	ssize_t tbufsz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
17217887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
17227887SLiane.Praza@Sun.COM 	scf_snaplevel_t *snaplvl = NULL;
17237887SLiane.Praza@Sun.COM 	scf_service_t *svc = NULL;
17247887SLiane.Praza@Sun.COM 	scf_handle_t *h;
17257887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
172611750SAntonello.Cruz@Sun.COM 	pg_tmpl_walk_t *p = NULL;
17277887SLiane.Praza@Sun.COM 
17287887SLiane.Praza@Sun.COM 	assert(fbufsz != 0 && nbufsz != 0 && tbufsz != 0);
17297887SLiane.Praza@Sun.COM 
17307887SLiane.Praza@Sun.COM 	scf_tmpl_pg_reset(pg_tmpl);
17317887SLiane.Praza@Sun.COM 
17327887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL)
17337887SLiane.Praza@Sun.COM 		return (-1);
17347887SLiane.Praza@Sun.COM 
17357887SLiane.Praza@Sun.COM 	if ((inst = scf_instance_create(h)) == NULL ||
17367887SLiane.Praza@Sun.COM 	    (svc = scf_service_create(h)) == NULL ||
17377887SLiane.Praza@Sun.COM 	    (snaplvl = scf_snaplevel_create(h)) == NULL) {
173811750SAntonello.Cruz@Sun.COM 		goto fail;
17397887SLiane.Praza@Sun.COM 	}
17407887SLiane.Praza@Sun.COM 
17417887SLiane.Praza@Sun.COM 	if ((fmribuf = malloc(fbufsz)) == NULL ||
17427887SLiane.Praza@Sun.COM 	    (pg_name = malloc(nbufsz)) == NULL ||
17437887SLiane.Praza@Sun.COM 	    (pg_type = malloc(tbufsz)) == NULL ||
17447887SLiane.Praza@Sun.COM 	    (p = calloc(1, sizeof (pg_tmpl_walk_t))) == NULL) {
17457887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
174611750SAntonello.Cruz@Sun.COM 		goto fail;
17477887SLiane.Praza@Sun.COM 	}
17487887SLiane.Praza@Sun.COM 
17497887SLiane.Praza@Sun.COM 	if (scf_pg_get_name(pg, pg_name, nbufsz) < 0) {
17507887SLiane.Praza@Sun.COM 		goto fail;
17517887SLiane.Praza@Sun.COM 	}
17527887SLiane.Praza@Sun.COM 
17537887SLiane.Praza@Sun.COM 	if (scf_pg_get_type(pg, pg_type, tbufsz) < 0) {
17547887SLiane.Praza@Sun.COM 		goto fail;
17557887SLiane.Praza@Sun.COM 	}
17567887SLiane.Praza@Sun.COM 	p->pw_pgname = pg_name;
17577887SLiane.Praza@Sun.COM 	p->pw_pgtype = pg_type;
17587887SLiane.Praza@Sun.COM 
17597887SLiane.Praza@Sun.COM 	ret = scf_pg_get_parent_snaplevel(pg, snaplvl);
17607887SLiane.Praza@Sun.COM 	if (ret == -1) {
17617887SLiane.Praza@Sun.COM 		switch (scf_error()) {
17627887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
17637887SLiane.Praza@Sun.COM 			/* Parent type doesn't match.  Keep looking. */
17647887SLiane.Praza@Sun.COM 			break;
17657887SLiane.Praza@Sun.COM 
17667887SLiane.Praza@Sun.COM 		case SCF_ERROR_DELETED:
17677887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_BOUND:
17687887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
17697887SLiane.Praza@Sun.COM 			/* Pass these back to the caller. */
17707887SLiane.Praza@Sun.COM 			goto fail;
17717887SLiane.Praza@Sun.COM 
17727887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
17737887SLiane.Praza@Sun.COM 		default:
17747887SLiane.Praza@Sun.COM 			assert(0);
17757887SLiane.Praza@Sun.COM 			abort();
17767887SLiane.Praza@Sun.COM 		}
17777887SLiane.Praza@Sun.COM 
17787887SLiane.Praza@Sun.COM 		/*
17797887SLiane.Praza@Sun.COM 		 * No snapshot.  We'll use 'editing' by default since
17807887SLiane.Praza@Sun.COM 		 * snap and snapbuf are NULL.
17817887SLiane.Praza@Sun.COM 		 */
17827887SLiane.Praza@Sun.COM 		p->pw_snapname = NULL;
17837887SLiane.Praza@Sun.COM 
17847887SLiane.Praza@Sun.COM 	} else {
17857887SLiane.Praza@Sun.COM 		if ((snap = scf_snapshot_create(h)) == NULL) {
17867887SLiane.Praza@Sun.COM 			goto fail;
17877887SLiane.Praza@Sun.COM 		}
17887887SLiane.Praza@Sun.COM 
17897887SLiane.Praza@Sun.COM 		ret = scf_snaplevel_get_parent(snaplvl, snap);
17907887SLiane.Praza@Sun.COM 		if (ret == -1) {
17917887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
17927887SLiane.Praza@Sun.COM 				goto fail;
17937887SLiane.Praza@Sun.COM 			} else {
17947887SLiane.Praza@Sun.COM 				assert(0);
17957887SLiane.Praza@Sun.COM 				abort();
17967887SLiane.Praza@Sun.COM 			}
17977887SLiane.Praza@Sun.COM 		}
17987887SLiane.Praza@Sun.COM 
17997887SLiane.Praza@Sun.COM 		/* Grab snapshot name while we're here. */
18007887SLiane.Praza@Sun.COM 		if ((snapbuf = malloc(nbufsz)) == NULL) {
18017887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
18027887SLiane.Praza@Sun.COM 			goto fail;
18037887SLiane.Praza@Sun.COM 		}
18047887SLiane.Praza@Sun.COM 		if (scf_snapshot_get_name(snap, snapbuf, nbufsz) < 0) {
18057887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
18067887SLiane.Praza@Sun.COM 				goto fail;
18077887SLiane.Praza@Sun.COM 			} else {
18087887SLiane.Praza@Sun.COM 				assert(0);
18097887SLiane.Praza@Sun.COM 				abort();
18107887SLiane.Praza@Sun.COM 			}
18117887SLiane.Praza@Sun.COM 		}
18127887SLiane.Praza@Sun.COM 		p->pw_snapname = snapbuf;
18137887SLiane.Praza@Sun.COM 
18147887SLiane.Praza@Sun.COM 		ret = scf_snapshot_get_parent(snap, inst);
18157887SLiane.Praza@Sun.COM 		if (ret == -1) {
18167887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
18177887SLiane.Praza@Sun.COM 				goto fail;
18187887SLiane.Praza@Sun.COM 			} else {
18197887SLiane.Praza@Sun.COM 				assert(0);
18207887SLiane.Praza@Sun.COM 				abort();
18217887SLiane.Praza@Sun.COM 			}
18227887SLiane.Praza@Sun.COM 		}
18237887SLiane.Praza@Sun.COM 
18247887SLiane.Praza@Sun.COM 		_walk_template_instances(NULL, inst, snap,
18257887SLiane.Praza@Sun.COM 		    (walk_template_inst_func_t *)find_pg_match, p, flags);
18267887SLiane.Praza@Sun.COM 	}
18277887SLiane.Praza@Sun.COM 
18287887SLiane.Praza@Sun.COM 	/* No snapshot parent.  Go looking for instance parent. */
18297887SLiane.Praza@Sun.COM 	if (snapbuf == NULL) {
18307887SLiane.Praza@Sun.COM 		/* First look for instance parent. */
18317887SLiane.Praza@Sun.COM 		ret = scf_pg_get_parent_instance(pg, inst);
18327887SLiane.Praza@Sun.COM 		if (ret == 0) {
18337887SLiane.Praza@Sun.COM 			_walk_template_instances(NULL, inst, snap,
18347887SLiane.Praza@Sun.COM 			    (walk_template_inst_func_t *)find_pg_match,
18357887SLiane.Praza@Sun.COM 			    p, flags);
18367887SLiane.Praza@Sun.COM 		/* OK, check for service parent */
18377887SLiane.Praza@Sun.COM 		} else if (ret == -1 &&
18387887SLiane.Praza@Sun.COM 		    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
18397887SLiane.Praza@Sun.COM 			ret = scf_pg_get_parent_service(pg, svc);
18407887SLiane.Praza@Sun.COM 			if (ret == 0) {
18417887SLiane.Praza@Sun.COM 				_walk_template_instances(svc, NULL, snap,
18427887SLiane.Praza@Sun.COM 				    (walk_template_inst_func_t *)find_pg_match,
18437887SLiane.Praza@Sun.COM 				    p, flags);
18447887SLiane.Praza@Sun.COM 			} else {
18457887SLiane.Praza@Sun.COM 				switch (scf_error()) {
18467887SLiane.Praza@Sun.COM 				case SCF_ERROR_CONSTRAINT_VIOLATED:
18477887SLiane.Praza@Sun.COM 					(void) scf_set_error(
18487887SLiane.Praza@Sun.COM 					    SCF_ERROR_NOT_FOUND);
18497887SLiane.Praza@Sun.COM 					/*FALLTHROUGH*/
18507887SLiane.Praza@Sun.COM 
18517887SLiane.Praza@Sun.COM 				case SCF_ERROR_CONNECTION_BROKEN:
18527887SLiane.Praza@Sun.COM 				case SCF_ERROR_DELETED:
18537887SLiane.Praza@Sun.COM 				case SCF_ERROR_HANDLE_MISMATCH:
18547887SLiane.Praza@Sun.COM 				case SCF_ERROR_NOT_BOUND:
18557887SLiane.Praza@Sun.COM 				case SCF_ERROR_NOT_SET:
18567887SLiane.Praza@Sun.COM 					goto fail;
18577887SLiane.Praza@Sun.COM 
18587887SLiane.Praza@Sun.COM 				default:
18597887SLiane.Praza@Sun.COM 					assert(0);
18607887SLiane.Praza@Sun.COM 					abort();
18617887SLiane.Praza@Sun.COM 				}
18627887SLiane.Praza@Sun.COM 			}
18637887SLiane.Praza@Sun.COM 		} else {
18647887SLiane.Praza@Sun.COM 			goto fail;
18657887SLiane.Praza@Sun.COM 		}
18667887SLiane.Praza@Sun.COM 	}
18677887SLiane.Praza@Sun.COM 
18687887SLiane.Praza@Sun.COM 	if (p->pw_pg != NULL) {
18697887SLiane.Praza@Sun.COM 		pg_tmpl->pt_h = h;
18707887SLiane.Praza@Sun.COM 		pg_tmpl->pt_pg = p->pw_pg;
18717887SLiane.Praza@Sun.COM 		pg_tmpl->pt_inst = p->pw_inst;
187211750SAntonello.Cruz@Sun.COM 		/* we may get a different instance back */
187311750SAntonello.Cruz@Sun.COM 		if (p->pw_inst != inst)
187411750SAntonello.Cruz@Sun.COM 			scf_instance_destroy(inst);
18757887SLiane.Praza@Sun.COM 		pg_tmpl->pt_snap = p->pw_snap;
18767887SLiane.Praza@Sun.COM 		pg_tmpl->pt_svc = p->pw_svc;
187711750SAntonello.Cruz@Sun.COM 		/* we may get a different service back */
187811750SAntonello.Cruz@Sun.COM 		if (p->pw_svc != svc)
187911750SAntonello.Cruz@Sun.COM 			scf_service_destroy(svc);
18807887SLiane.Praza@Sun.COM 		pg_tmpl->pt_populated = 1;
18817887SLiane.Praza@Sun.COM 		free(p->pw_tmpl_pgname);
18827887SLiane.Praza@Sun.COM 		ret = 0;
18837887SLiane.Praza@Sun.COM 		goto done;
18847887SLiane.Praza@Sun.COM 	}
18857887SLiane.Praza@Sun.COM 
18867887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NOT_FOUND);
18877887SLiane.Praza@Sun.COM 
18887887SLiane.Praza@Sun.COM fail:
188911750SAntonello.Cruz@Sun.COM 	ret = -1;
18907887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
18917887SLiane.Praza@Sun.COM 	scf_service_destroy(svc);
189211750SAntonello.Cruz@Sun.COM done:
18937887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
18947887SLiane.Praza@Sun.COM 	free(snapbuf);
18957887SLiane.Praza@Sun.COM 	free(fmribuf);
18967887SLiane.Praza@Sun.COM 	free(pg_name);
18977887SLiane.Praza@Sun.COM 	free(pg_type);
18987887SLiane.Praza@Sun.COM 	free(p);
18997887SLiane.Praza@Sun.COM 	scf_snaplevel_destroy(snaplvl);
19007887SLiane.Praza@Sun.COM 	return (ret);
19017887SLiane.Praza@Sun.COM }
19027887SLiane.Praza@Sun.COM 
19037887SLiane.Praza@Sun.COM /*
19047887SLiane.Praza@Sun.COM  * int scf_tmpl_get_by_pg_name()
19057887SLiane.Praza@Sun.COM  *
19067887SLiane.Praza@Sun.COM  * Get a template by a combination of the name and type.  Either name
19077887SLiane.Praza@Sun.COM  * or type can be null, which indicates a wildcard.  flags may be
19087887SLiane.Praza@Sun.COM  * SCF_PG_TMPL_FLAG_CURRENT (use current properties rather than
19097887SLiane.Praza@Sun.COM  * the defined or running snapshot), and SCF_PG_TMPL_FLAG_EXACT (match
19107887SLiane.Praza@Sun.COM  * only templates defined by the FMRI in question, not by its restarter
19117887SLiane.Praza@Sun.COM  * or globally).  Returns 0 on success and -1 on error, and sets
19127887SLiane.Praza@Sun.COM  * scf_error() to:
19137887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
19147887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
19157887SLiane.Praza@Sun.COM  *     The connection to the repository was lost.
19167887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
19177887SLiane.Praza@Sun.COM  *     The instance has been deleted.
19187887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
19197887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
19207887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
19217887SLiane.Praza@Sun.COM  *     FMRI isn't valid, pg_name is too long to look for a template, or
19227887SLiane.Praza@Sun.COM  *     snapshot specified isn't a valid name
19237887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
19247887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
19257887SLiane.Praza@Sun.COM  *     The server does not have adequate resources to complete the request.
19267887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
19277887SLiane.Praza@Sun.COM  *     The handle is not currently bound.
19287887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
19297887SLiane.Praza@Sun.COM  *     Object matching FMRI doesn't exist in the repository, or snapshot
19307887SLiane.Praza@Sun.COM  *     doesn't exist.
19317887SLiane.Praza@Sun.COM  */
19327887SLiane.Praza@Sun.COM int
scf_tmpl_get_by_pg_name(const char * fmri,const char * snapshot,const char * pg_name,const char * pg_type,scf_pg_tmpl_t * pg_tmpl,int flags)19337887SLiane.Praza@Sun.COM scf_tmpl_get_by_pg_name(const char *fmri, const char *snapshot,
19347887SLiane.Praza@Sun.COM     const char *pg_name, const char *pg_type, scf_pg_tmpl_t *pg_tmpl, int flags)
19357887SLiane.Praza@Sun.COM {
19367887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
19377887SLiane.Praza@Sun.COM 	scf_service_t *svc = NULL;
19387887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
193911750SAntonello.Cruz@Sun.COM 	pg_tmpl_walk_t *p = NULL;
19407887SLiane.Praza@Sun.COM 	scf_handle_t *h;
19417887SLiane.Praza@Sun.COM 	int ret;
19427887SLiane.Praza@Sun.COM 
19437887SLiane.Praza@Sun.COM 	assert(pg_tmpl != NULL);
19447887SLiane.Praza@Sun.COM 	h = pg_tmpl->pt_h;
19457887SLiane.Praza@Sun.COM 	assert(h != NULL);
19467887SLiane.Praza@Sun.COM 
19477887SLiane.Praza@Sun.COM 	scf_tmpl_pg_reset(pg_tmpl);
19487887SLiane.Praza@Sun.COM 
19497887SLiane.Praza@Sun.COM 	if ((inst = scf_instance_create(h)) == NULL ||
19507887SLiane.Praza@Sun.COM 	    (svc = scf_service_create(h)) == NULL) {
195111750SAntonello.Cruz@Sun.COM 		goto fail;
19527887SLiane.Praza@Sun.COM 	}
19537887SLiane.Praza@Sun.COM 
19547887SLiane.Praza@Sun.COM 	p = calloc(1, sizeof (pg_tmpl_walk_t));
19557887SLiane.Praza@Sun.COM 	if (p == NULL) {
19567887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
195711750SAntonello.Cruz@Sun.COM 		goto fail;
19587887SLiane.Praza@Sun.COM 	}
19597887SLiane.Praza@Sun.COM 
19607887SLiane.Praza@Sun.COM 	ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL,
19617887SLiane.Praza@Sun.COM 	    NULL, SCF_DECODE_FMRI_EXACT);
19627887SLiane.Praza@Sun.COM 	if (ret == 0) {
19637887SLiane.Praza@Sun.COM 		scf_service_destroy(svc);
19647887SLiane.Praza@Sun.COM 		svc = NULL;
19657887SLiane.Praza@Sun.COM 	} else if (ret != 0 &&
19667887SLiane.Praza@Sun.COM 	    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
19677887SLiane.Praza@Sun.COM 		ret = scf_handle_decode_fmri(h, fmri, NULL, svc,
19687887SLiane.Praza@Sun.COM 		    NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT);
19697887SLiane.Praza@Sun.COM 		if (ret == 0) {
19707887SLiane.Praza@Sun.COM 			scf_instance_destroy(inst);
19717887SLiane.Praza@Sun.COM 			inst = NULL;
19727887SLiane.Praza@Sun.COM 		}
19737887SLiane.Praza@Sun.COM 	}
19747887SLiane.Praza@Sun.COM 	if (ret != 0) {
19757887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
19767887SLiane.Praza@Sun.COM 			goto fail;
19777887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
19787887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
19797887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
19807887SLiane.Praza@Sun.COM 			goto fail;
19817887SLiane.Praza@Sun.COM 
19827887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
19837887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
19847887SLiane.Praza@Sun.COM 			goto fail;
19857887SLiane.Praza@Sun.COM 
19867887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
19877887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
19887887SLiane.Praza@Sun.COM 		default:
19897887SLiane.Praza@Sun.COM 			assert(0);
19907887SLiane.Praza@Sun.COM 			abort();
19917887SLiane.Praza@Sun.COM 		}
19927887SLiane.Praza@Sun.COM 	}
19937887SLiane.Praza@Sun.COM 
19947887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
19957887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
19967887SLiane.Praza@Sun.COM 
199711750SAntonello.Cruz@Sun.COM 	/* If we have a service fmri, snapshot is ignored. */
19987887SLiane.Praza@Sun.COM 	if (inst != NULL) {
19997887SLiane.Praza@Sun.COM 		if (snapshot == NULL || strcmp(snapshot, "running") == 0 ||
20007887SLiane.Praza@Sun.COM 		    (flags & SCF_PG_TMPL_FLAG_CURRENT) ==
20017887SLiane.Praza@Sun.COM 		    SCF_PG_TMPL_FLAG_CURRENT) {
20027887SLiane.Praza@Sun.COM 			if (_get_snapshot(inst, NULL, &snap) == -1)
20037887SLiane.Praza@Sun.COM 				goto fail;
20047887SLiane.Praza@Sun.COM 		} else {
20057887SLiane.Praza@Sun.COM 			if (_get_snapshot(inst, snapshot, &snap) == -1) {
20067887SLiane.Praza@Sun.COM 				goto fail;
20077887SLiane.Praza@Sun.COM 			} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
20087887SLiane.Praza@Sun.COM 				goto fail;
20097887SLiane.Praza@Sun.COM 			}
20107887SLiane.Praza@Sun.COM 		}
20117887SLiane.Praza@Sun.COM 	}
20127887SLiane.Praza@Sun.COM 
20137887SLiane.Praza@Sun.COM 	p->pw_snapname = snapshot;
20147887SLiane.Praza@Sun.COM 	p->pw_pgname = pg_name;
20157887SLiane.Praza@Sun.COM 	p->pw_pgtype = pg_type;
20167887SLiane.Praza@Sun.COM 
20177887SLiane.Praza@Sun.COM 	/*
20187887SLiane.Praza@Sun.COM 	 * For each of instance, restarter, global
20197887SLiane.Praza@Sun.COM 	 *    - check for a tm_pg_pattern_nt_<name> matching type
20207887SLiane.Praza@Sun.COM 	 *    - check for a tm_pg_pattern_t_<type> matching type
20217887SLiane.Praza@Sun.COM 	 *    - check for any tm_pg_pattern_
20227887SLiane.Praza@Sun.COM 	 * Currently plan to return the most specific match only.
20237887SLiane.Praza@Sun.COM 	 */
20247887SLiane.Praza@Sun.COM 	_walk_template_instances(svc, inst, snap,
20257887SLiane.Praza@Sun.COM 	    (walk_template_inst_func_t *)find_pg_match, p, flags);
20267887SLiane.Praza@Sun.COM 
20277887SLiane.Praza@Sun.COM 	if (p->pw_pg != NULL) {
20287887SLiane.Praza@Sun.COM 		pg_tmpl->pt_h = h;
20297887SLiane.Praza@Sun.COM 		pg_tmpl->pt_pg = p->pw_pg;
20307887SLiane.Praza@Sun.COM 		pg_tmpl->pt_inst = p->pw_inst;
203111750SAntonello.Cruz@Sun.COM 		/* we may get a different instance back */
203211750SAntonello.Cruz@Sun.COM 		if (p->pw_inst != inst)
203311750SAntonello.Cruz@Sun.COM 			scf_instance_destroy(inst);
20347887SLiane.Praza@Sun.COM 		pg_tmpl->pt_snap = p->pw_snap;
20357887SLiane.Praza@Sun.COM 		pg_tmpl->pt_svc = p->pw_svc;
203611750SAntonello.Cruz@Sun.COM 		/* we may get a different service back */
203711750SAntonello.Cruz@Sun.COM 		if (p->pw_svc != svc)
203811750SAntonello.Cruz@Sun.COM 			scf_service_destroy(svc);
20397887SLiane.Praza@Sun.COM 		pg_tmpl->pt_populated = 1;
204011750SAntonello.Cruz@Sun.COM 		scf_snapshot_destroy(snap);
20417887SLiane.Praza@Sun.COM 		free(p->pw_tmpl_pgname);
20427887SLiane.Praza@Sun.COM 		free(p);
20437887SLiane.Praza@Sun.COM 		return (0);
20447887SLiane.Praza@Sun.COM 	}
20457887SLiane.Praza@Sun.COM 
20467887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NOT_FOUND);
20477887SLiane.Praza@Sun.COM fail:
20487887SLiane.Praza@Sun.COM 	free(p);
20497887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
20507887SLiane.Praza@Sun.COM 	scf_service_destroy(svc);
20517887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
20527887SLiane.Praza@Sun.COM 	return (-1);
20537887SLiane.Praza@Sun.COM }
20547887SLiane.Praza@Sun.COM 
20557887SLiane.Praza@Sun.COM /*
20567887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _CONNECTION_BROKEN,
20577887SLiane.Praza@Sun.COM  * _DELETED, _NO_RESOURCES, or _NOT_BOUND.
20587887SLiane.Praza@Sun.COM  */
20597887SLiane.Praza@Sun.COM static scf_iter_t *
_get_svc_or_inst_iter(scf_handle_t * h,scf_pg_tmpl_t * t)20607887SLiane.Praza@Sun.COM _get_svc_or_inst_iter(scf_handle_t *h, scf_pg_tmpl_t *t)
20617887SLiane.Praza@Sun.COM {
20627887SLiane.Praza@Sun.COM 	scf_iter_t *iter;
20637887SLiane.Praza@Sun.COM 	int ret;
20647887SLiane.Praza@Sun.COM 
20657887SLiane.Praza@Sun.COM 	assert(t->pt_svc != NULL || t->pt_inst != NULL);
20667887SLiane.Praza@Sun.COM 	assert(t->pt_svc == NULL || t->pt_inst == NULL);
20677887SLiane.Praza@Sun.COM 
20687887SLiane.Praza@Sun.COM 	if ((iter = scf_iter_create(h)) == NULL) {
20697887SLiane.Praza@Sun.COM 		return (NULL);
20707887SLiane.Praza@Sun.COM 	}
20717887SLiane.Praza@Sun.COM 
20727887SLiane.Praza@Sun.COM 	/* Iterate on property groups of type template_pg_pattern */
20737887SLiane.Praza@Sun.COM 
20747887SLiane.Praza@Sun.COM 	if (t->pt_inst != NULL)
20757887SLiane.Praza@Sun.COM 		ret = scf_iter_instance_pgs_typed_composed(iter,
20767887SLiane.Praza@Sun.COM 		    t->pt_inst, t->pt_snap,
20777887SLiane.Praza@Sun.COM 		    SCF_GROUP_TEMPLATE_PG_PATTERN);
20787887SLiane.Praza@Sun.COM 	if (t->pt_svc != NULL)
20797887SLiane.Praza@Sun.COM 		ret = scf_iter_service_pgs_typed(iter, t->pt_svc,
20807887SLiane.Praza@Sun.COM 		    SCF_GROUP_TEMPLATE_PG_PATTERN);
20817887SLiane.Praza@Sun.COM 
20827887SLiane.Praza@Sun.COM 	if (ret != 0) {
20837887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
20847887SLiane.Praza@Sun.COM 			scf_iter_destroy(iter);
20857887SLiane.Praza@Sun.COM 			return (NULL);
20867887SLiane.Praza@Sun.COM 		} else {
20877887SLiane.Praza@Sun.COM 			assert(0);
20887887SLiane.Praza@Sun.COM 			abort();
20897887SLiane.Praza@Sun.COM 		}
20907887SLiane.Praza@Sun.COM 	}
20917887SLiane.Praza@Sun.COM 
20927887SLiane.Praza@Sun.COM 	return (iter);
20937887SLiane.Praza@Sun.COM }
20947887SLiane.Praza@Sun.COM 
20957887SLiane.Praza@Sun.COM /*
20967887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
20977887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
20987887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
20997887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
21007887SLiane.Praza@Sun.COM  *   SCF_HANDLE_DESTROYED
21017887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
21027887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
21037887SLiane.Praza@Sun.COM  *     Handle argument is NULL, or snaphot is not a valid snapshot name.
21047887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
21057887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
21067887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
21077887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
21087887SLiane.Praza@Sun.COM  */
21097887SLiane.Praza@Sun.COM static scf_iter_t *
_get_next_iterator(scf_handle_t * h,scf_pg_tmpl_t * t,const char * snapshot,int exact)21107887SLiane.Praza@Sun.COM _get_next_iterator(scf_handle_t *h, scf_pg_tmpl_t *t, const char *snapshot,
21117887SLiane.Praza@Sun.COM     int exact)
21127887SLiane.Praza@Sun.COM {
21137887SLiane.Praza@Sun.COM 	scf_iter_t  *iter = NULL;
21147887SLiane.Praza@Sun.COM 	ssize_t limit;
21157887SLiane.Praza@Sun.COM 
21167887SLiane.Praza@Sun.COM 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
21177887SLiane.Praza@Sun.COM 	assert(limit != 0);
21187887SLiane.Praza@Sun.COM 
21197887SLiane.Praza@Sun.COM 	/*
21207887SLiane.Praza@Sun.COM 	 * Check what level we last iterated on: none, service,
21217887SLiane.Praza@Sun.COM 	 * restarter, or global.  Make sure that if one in the middle
21227887SLiane.Praza@Sun.COM 	 * doesn't exist, we move on to the next entity.
212311750SAntonello.Cruz@Sun.COM 	 *
212411750SAntonello.Cruz@Sun.COM 	 * Before we drop any references to pt_inst or pt_svc we must
212511750SAntonello.Cruz@Sun.COM 	 * destroy them so we don't leak them.
21267887SLiane.Praza@Sun.COM 	 */
21277887SLiane.Praza@Sun.COM 	do {
21287887SLiane.Praza@Sun.COM 		switch (t->pt_iter_last) {
21297887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_NONE:
21307887SLiane.Praza@Sun.COM 			t->pt_iter_last = SCF__TMPL_ITER_INST;
213111750SAntonello.Cruz@Sun.COM 			if (t->pt_inst != t->pt_orig_inst)
213211750SAntonello.Cruz@Sun.COM 				scf_instance_destroy(t->pt_inst);
21337887SLiane.Praza@Sun.COM 			t->pt_inst = t->pt_orig_inst;
213411750SAntonello.Cruz@Sun.COM 			if (t->pt_svc != t->pt_orig_svc)
213511750SAntonello.Cruz@Sun.COM 				scf_service_destroy(t->pt_svc);
21367887SLiane.Praza@Sun.COM 			t->pt_svc = t->pt_orig_svc;
21377887SLiane.Praza@Sun.COM 			break;
21387887SLiane.Praza@Sun.COM 
21397887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_INST:
21407887SLiane.Praza@Sun.COM 			/*
21417887SLiane.Praza@Sun.COM 			 * Don't go any further than the specified instance
21427887SLiane.Praza@Sun.COM 			 * if exact was set.
21437887SLiane.Praza@Sun.COM 			 */
21447887SLiane.Praza@Sun.COM 			if (exact == 1) {
21457887SLiane.Praza@Sun.COM 				(void) scf_set_error(SCF_ERROR_NOT_FOUND);
21467887SLiane.Praza@Sun.COM 				goto fail;
21477887SLiane.Praza@Sun.COM 			}
21487887SLiane.Praza@Sun.COM 			t->pt_iter_last = SCF__TMPL_ITER_RESTARTER;
214911750SAntonello.Cruz@Sun.COM 			if (t->pt_inst != t->pt_orig_inst)
215011750SAntonello.Cruz@Sun.COM 				scf_instance_destroy(t->pt_inst);
21517887SLiane.Praza@Sun.COM 			t->pt_inst = _get_restarter_inst(h, t->pt_orig_svc,
21527887SLiane.Praza@Sun.COM 			    t->pt_orig_inst, t->pt_snap);
215311750SAntonello.Cruz@Sun.COM 			scf_service_destroy(t->pt_svc);
21547887SLiane.Praza@Sun.COM 			t->pt_svc = NULL;
21557887SLiane.Praza@Sun.COM 			break;
21567887SLiane.Praza@Sun.COM 
21577887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_RESTARTER:
21587887SLiane.Praza@Sun.COM 			t->pt_iter_last = SCF__TMPL_ITER_GLOBAL;
215911750SAntonello.Cruz@Sun.COM 			if (t->pt_inst != t->pt_orig_inst)
216011750SAntonello.Cruz@Sun.COM 				scf_instance_destroy(t->pt_inst);
21617887SLiane.Praza@Sun.COM 			t->pt_inst = _get_global_inst(h);
216211750SAntonello.Cruz@Sun.COM 			scf_service_destroy(t->pt_svc);
21637887SLiane.Praza@Sun.COM 			t->pt_svc = NULL;
21647887SLiane.Praza@Sun.COM 			break;
21657887SLiane.Praza@Sun.COM 
21667887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_GLOBAL:
21677887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NOT_FOUND);
21687887SLiane.Praza@Sun.COM 			return (NULL);
21697887SLiane.Praza@Sun.COM 
21707887SLiane.Praza@Sun.COM 		default:
21717887SLiane.Praza@Sun.COM 			assert(0);
21727887SLiane.Praza@Sun.COM 			abort();
21737887SLiane.Praza@Sun.COM 		}
21747887SLiane.Praza@Sun.COM 	} while (t->pt_inst == NULL && t->pt_svc == NULL);
21757887SLiane.Praza@Sun.COM 
21767887SLiane.Praza@Sun.COM 	/* Set pt_snap to the snapshot for this instance */
21777887SLiane.Praza@Sun.COM 	if (t->pt_inst != NULL) {
21787887SLiane.Praza@Sun.COM 		scf_snapshot_destroy(t->pt_snap);
21797887SLiane.Praza@Sun.COM 		if (_get_snapshot(t->pt_inst, snapshot,
21807887SLiane.Praza@Sun.COM 		    &t->pt_snap) == -1)
21817887SLiane.Praza@Sun.COM 			goto fail;
21827887SLiane.Praza@Sun.COM 	}
21837887SLiane.Praza@Sun.COM 
21847887SLiane.Praza@Sun.COM 
21857887SLiane.Praza@Sun.COM 	iter = _get_svc_or_inst_iter(h, t);
21867887SLiane.Praza@Sun.COM fail:
21877887SLiane.Praza@Sun.COM 	return (iter);
21887887SLiane.Praza@Sun.COM }
21897887SLiane.Praza@Sun.COM 
21907887SLiane.Praza@Sun.COM /*
21917887SLiane.Praza@Sun.COM  * scf_pg_tmpl_t *scf_tmpl_pg_create(scf_handle_t *)
21927887SLiane.Praza@Sun.COM  *
21937887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT
21947887SLiane.Praza@Sun.COM  * or _NO_MEMORY.
21957887SLiane.Praza@Sun.COM  */
21967887SLiane.Praza@Sun.COM scf_pg_tmpl_t *
scf_tmpl_pg_create(scf_handle_t * handle)21977887SLiane.Praza@Sun.COM scf_tmpl_pg_create(scf_handle_t *handle)
21987887SLiane.Praza@Sun.COM {
21997887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *pg_tmpl = NULL;
22007887SLiane.Praza@Sun.COM 
22017887SLiane.Praza@Sun.COM 	if (handle == NULL) {
22027887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
22037887SLiane.Praza@Sun.COM 		return (NULL);
22047887SLiane.Praza@Sun.COM 	}
22057887SLiane.Praza@Sun.COM 	pg_tmpl = calloc(1, sizeof (scf_pg_tmpl_t));
22067887SLiane.Praza@Sun.COM 	if (pg_tmpl == NULL)
22077887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
22087887SLiane.Praza@Sun.COM 	else
22097887SLiane.Praza@Sun.COM 		pg_tmpl->pt_h = handle;
22107887SLiane.Praza@Sun.COM 
22117887SLiane.Praza@Sun.COM 	return (pg_tmpl);
22127887SLiane.Praza@Sun.COM }
22137887SLiane.Praza@Sun.COM 
22147887SLiane.Praza@Sun.COM /*
22157887SLiane.Praza@Sun.COM  * Retrieves name or type of a template pg.
22167887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
22177887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
22187887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
22197887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
22207887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
22217887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
22227887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
22237887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
22247887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
22257887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
22267887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
22277887SLiane.Praza@Sun.COM  *     pname property is not SCF_TYPE_ASTRING or has more than one value.
22287887SLiane.Praza@Sun.COM  */
22297887SLiane.Praza@Sun.COM static ssize_t
_scf_tmpl_prop_value(scf_propertygroup_t * pg,const char * pname,char ** out)22307887SLiane.Praza@Sun.COM _scf_tmpl_prop_value(scf_propertygroup_t *pg, const char *pname, char **out)
22317887SLiane.Praza@Sun.COM {
22327887SLiane.Praza@Sun.COM 	assert(strcmp(pname, SCF_PROPERTY_TM_NAME) == 0 ||
22337887SLiane.Praza@Sun.COM 	    strcmp(pname, SCF_PROPERTY_TM_TYPE) == 0);
22347887SLiane.Praza@Sun.COM 
22357887SLiane.Praza@Sun.COM 	*out = _scf_read_single_astring_from_pg(pg, pname);
22367887SLiane.Praza@Sun.COM 
22377887SLiane.Praza@Sun.COM 	if (*out != NULL && *out[0] == '\0') {
22387887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NONE);
22397887SLiane.Praza@Sun.COM 		free(*out);
22407887SLiane.Praza@Sun.COM 		*out = strdup(SCF_TMPL_WILDCARD);
22417887SLiane.Praza@Sun.COM 		if (*out == NULL)
22427887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
22437887SLiane.Praza@Sun.COM 	}
22447887SLiane.Praza@Sun.COM 	if (*out == NULL) {
22457887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
22467887SLiane.Praza@Sun.COM 			return (-1);
22477887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
22487887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
22497887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
22507887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
22517887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
22527887SLiane.Praza@Sun.COM 			return (-1);
22537887SLiane.Praza@Sun.COM 
22547887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
22557887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
22567887SLiane.Praza@Sun.COM 		default:
22577887SLiane.Praza@Sun.COM 			assert(0);
22587887SLiane.Praza@Sun.COM 			abort();
22597887SLiane.Praza@Sun.COM 		}
22607887SLiane.Praza@Sun.COM 	}
22617887SLiane.Praza@Sun.COM 
22627887SLiane.Praza@Sun.COM 	return (strlen(*out));
22637887SLiane.Praza@Sun.COM }
22647887SLiane.Praza@Sun.COM 
22657887SLiane.Praza@Sun.COM /*
22667887SLiane.Praza@Sun.COM  * int scf_tmpl_iter_pgs()
22677887SLiane.Praza@Sun.COM  *
22687887SLiane.Praza@Sun.COM  * Iterates through the property group templates for the fmri given.
22697887SLiane.Praza@Sun.COM  * When t is uninitialized or reset, sets t to the first property group
22707887SLiane.Praza@Sun.COM  * template in fmri. On subsequent calls, sets t to the next property group
22717887SLiane.Praza@Sun.COM  * template in frmi.
22727887SLiane.Praza@Sun.COM  * Returns 1 on success, 0 when no property group templates are left to
22737887SLiane.Praza@Sun.COM  * iterate, -1 on error.
22747887SLiane.Praza@Sun.COM  * The flags argument may include SCF_PG_TMPL_FLAG_REQUIRED,
22757887SLiane.Praza@Sun.COM  * SCF_PG_TMPL_FLAG_CURRENT,  and/or SCF_PG_TMPL_FLAG_EXACT.
22767887SLiane.Praza@Sun.COM  *
22777887SLiane.Praza@Sun.COM  * Returns -1 on error and sets scf_error() to:
22787887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
22797887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
22807887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
22817887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
22827887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
22837887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
22847887SLiane.Praza@Sun.COM  *      The handle argument is NULL, fmri is invalid, or snapshot is invalid.
22857887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
22867887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
22877887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
22887887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
22897887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
22907887SLiane.Praza@Sun.COM  */
22917887SLiane.Praza@Sun.COM int
scf_tmpl_iter_pgs(scf_pg_tmpl_t * t,const char * fmri,const char * snapshot,const char * type,int flags)22927887SLiane.Praza@Sun.COM scf_tmpl_iter_pgs(scf_pg_tmpl_t *t, const char *fmri, const char *snapshot,
22937887SLiane.Praza@Sun.COM     const char *type, int flags)
22947887SLiane.Praza@Sun.COM {
22957887SLiane.Praza@Sun.COM 	scf_handle_t *h;
22967887SLiane.Praza@Sun.COM 	scf_service_t *svc = NULL;
22977887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
22987887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
22997887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
23007887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *pg_tmpl = NULL;
23017887SLiane.Praza@Sun.COM 	int err;
23027887SLiane.Praza@Sun.COM 	int found = 0;
23037887SLiane.Praza@Sun.COM 	char *tmpl_type;
23047887SLiane.Praza@Sun.COM 	uint8_t required;
23057887SLiane.Praza@Sun.COM 	int ret;
23067887SLiane.Praza@Sun.COM 
23077887SLiane.Praza@Sun.COM 	if (t == NULL) {
23087887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
23097887SLiane.Praza@Sun.COM 		return (-1);
23107887SLiane.Praza@Sun.COM 	}
23117887SLiane.Praza@Sun.COM 
23127887SLiane.Praza@Sun.COM 	h = t->pt_h;
23137887SLiane.Praza@Sun.COM 
23147887SLiane.Praza@Sun.COM 	if (t->pt_populated == 0) {
23157887SLiane.Praza@Sun.COM 		if ((svc = scf_service_create(h)) == NULL ||
23167887SLiane.Praza@Sun.COM 		    (inst = scf_instance_create(h)) == NULL ||
23177887SLiane.Praza@Sun.COM 		    (pg = scf_pg_create(h)) == NULL) {
23187887SLiane.Praza@Sun.COM 			goto fail_non_populated;
23197887SLiane.Praza@Sun.COM 		}
23207887SLiane.Praza@Sun.COM 
23217887SLiane.Praza@Sun.COM 		ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL,
23227887SLiane.Praza@Sun.COM 		    NULL, SCF_DECODE_FMRI_EXACT);
23237887SLiane.Praza@Sun.COM 		if (ret == 0) {
23247887SLiane.Praza@Sun.COM 			scf_service_destroy(svc);
23257887SLiane.Praza@Sun.COM 			svc = NULL;
23267887SLiane.Praza@Sun.COM 		} else if (ret != 0 &&
23277887SLiane.Praza@Sun.COM 		    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
23287887SLiane.Praza@Sun.COM 			ret = scf_handle_decode_fmri(h, fmri, NULL, svc,
23297887SLiane.Praza@Sun.COM 			    NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT);
23307887SLiane.Praza@Sun.COM 			if (ret == 0) {
23317887SLiane.Praza@Sun.COM 				scf_instance_destroy(inst);
23327887SLiane.Praza@Sun.COM 				inst = NULL;
23337887SLiane.Praza@Sun.COM 			}
23347887SLiane.Praza@Sun.COM 		}
23357887SLiane.Praza@Sun.COM 
23367887SLiane.Praza@Sun.COM 		if (ret != 0) {
23377887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
23387887SLiane.Praza@Sun.COM 				goto fail_non_populated;
23397887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
23407887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
23417887SLiane.Praza@Sun.COM 				(void) scf_set_error(
23427887SLiane.Praza@Sun.COM 				    SCF_ERROR_INVALID_ARGUMENT);
23437887SLiane.Praza@Sun.COM 				goto fail_non_populated;
23447887SLiane.Praza@Sun.COM 
23457887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
23467887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
23477887SLiane.Praza@Sun.COM 				goto fail_non_populated;
23487887SLiane.Praza@Sun.COM 
23497887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
23507887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
23517887SLiane.Praza@Sun.COM 			default:
23527887SLiane.Praza@Sun.COM 				assert(0);
23537887SLiane.Praza@Sun.COM 				abort();
23547887SLiane.Praza@Sun.COM 			}
23557887SLiane.Praza@Sun.COM 		}
23567887SLiane.Praza@Sun.COM 
23577887SLiane.Praza@Sun.COM 		assert(svc == NULL || inst == NULL);
23587887SLiane.Praza@Sun.COM 		assert(svc != NULL || inst != NULL);
23597887SLiane.Praza@Sun.COM 
23607887SLiane.Praza@Sun.COM 		if (inst != NULL) {
23617887SLiane.Praza@Sun.COM 			if (snapshot == NULL ||
23627887SLiane.Praza@Sun.COM 			    strcmp(snapshot, "running") == 0 ||
23637887SLiane.Praza@Sun.COM 			    (flags & SCF_PG_TMPL_FLAG_CURRENT) ==
23647887SLiane.Praza@Sun.COM 			    SCF_PG_TMPL_FLAG_CURRENT) {
23657887SLiane.Praza@Sun.COM 				if (_get_snapshot(inst, NULL, &snap) == -1)
23667887SLiane.Praza@Sun.COM 					goto fail_non_populated;
23677887SLiane.Praza@Sun.COM 			} else {
23687887SLiane.Praza@Sun.COM 				(void) scf_set_error(SCF_ERROR_NONE);
23697887SLiane.Praza@Sun.COM 				if (_get_snapshot(inst, snapshot,
23707887SLiane.Praza@Sun.COM 				    &snap) == -1) {
23717887SLiane.Praza@Sun.COM 					goto fail_non_populated;
23727887SLiane.Praza@Sun.COM 				} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
23737887SLiane.Praza@Sun.COM 					goto fail_non_populated;
23747887SLiane.Praza@Sun.COM 				}
23757887SLiane.Praza@Sun.COM 			}
23767887SLiane.Praza@Sun.COM 		} else {
23777887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(snap);
23787887SLiane.Praza@Sun.COM 			snap = NULL;
23797887SLiane.Praza@Sun.COM 		}
23807887SLiane.Praza@Sun.COM 
23817887SLiane.Praza@Sun.COM 		pg_tmpl = t;
23827887SLiane.Praza@Sun.COM 		pg_tmpl->pt_orig_inst = inst;
23837887SLiane.Praza@Sun.COM 		pg_tmpl->pt_orig_svc = svc;
23847887SLiane.Praza@Sun.COM 		pg_tmpl->pt_snap = snap;
23857887SLiane.Praza@Sun.COM 		pg_tmpl->pt_is_iter = 1;
23867887SLiane.Praza@Sun.COM 		pg_tmpl->pt_iter_last = SCF__TMPL_ITER_NONE;
23877887SLiane.Praza@Sun.COM 		pg_tmpl->pt_pg = pg;
23887887SLiane.Praza@Sun.COM 		pg_tmpl->pt_populated = 1;
23897887SLiane.Praza@Sun.COM 	} else {
23907887SLiane.Praza@Sun.COM 		if (t->pt_is_iter != 1) {
23917887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
23927887SLiane.Praza@Sun.COM 			return (-1);
23937887SLiane.Praza@Sun.COM 		}
23947887SLiane.Praza@Sun.COM 		pg_tmpl = t;
23957887SLiane.Praza@Sun.COM 		assert(pg_tmpl->pt_pg != NULL);
23967887SLiane.Praza@Sun.COM 	}
23977887SLiane.Praza@Sun.COM 
23987887SLiane.Praza@Sun.COM 	if (pg_tmpl->pt_iter == NULL) {
23997887SLiane.Praza@Sun.COM 		pg_tmpl->pt_iter = _get_next_iterator(h, pg_tmpl, snapshot,
24007887SLiane.Praza@Sun.COM 		    (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0);
24017887SLiane.Praza@Sun.COM 		if (pg_tmpl->pt_iter == NULL) {
24027887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
24037887SLiane.Praza@Sun.COM 				return (0);
24047887SLiane.Praza@Sun.COM 			else
24057887SLiane.Praza@Sun.COM 				return (-1);
24067887SLiane.Praza@Sun.COM 		}
24077887SLiane.Praza@Sun.COM 	}
24087887SLiane.Praza@Sun.COM 
24097887SLiane.Praza@Sun.COM 	while (found == 0) {
24107887SLiane.Praza@Sun.COM 		while ((err = scf_iter_next_pg(pg_tmpl->pt_iter,
24117887SLiane.Praza@Sun.COM 		    pg_tmpl->pt_pg)) != 1) {
24127887SLiane.Praza@Sun.COM 			if (err == -1) {
24137887SLiane.Praza@Sun.COM 				if (ismember(scf_error(), errors_server)) {
24147887SLiane.Praza@Sun.COM 					return (-1);
24157887SLiane.Praza@Sun.COM 				} else switch (scf_error()) {
24167887SLiane.Praza@Sun.COM 				case SCF_ERROR_HANDLE_MISMATCH:
24177887SLiane.Praza@Sun.COM 					return (-1);
24187887SLiane.Praza@Sun.COM 
24197887SLiane.Praza@Sun.COM 				case SCF_ERROR_NOT_SET:
24207887SLiane.Praza@Sun.COM 				case SCF_ERROR_INVALID_ARGUMENT:
24217887SLiane.Praza@Sun.COM 				default:
24227887SLiane.Praza@Sun.COM 					assert(0);
24237887SLiane.Praza@Sun.COM 					abort();
24247887SLiane.Praza@Sun.COM 				}
24257887SLiane.Praza@Sun.COM 			} else if (err == 0)  {
24267887SLiane.Praza@Sun.COM 				/* This iteration is done.  Get the next one */
24277887SLiane.Praza@Sun.COM 				scf_iter_destroy(pg_tmpl->pt_iter);
24287887SLiane.Praza@Sun.COM 				pg_tmpl->pt_iter = _get_next_iterator(h,
24297887SLiane.Praza@Sun.COM 				    pg_tmpl, snapshot,
24307887SLiane.Praza@Sun.COM 				    (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0);
24317887SLiane.Praza@Sun.COM 				if (pg_tmpl->pt_iter == NULL) {
24327887SLiane.Praza@Sun.COM 					if (scf_error() == SCF_ERROR_NOT_FOUND)
24337887SLiane.Praza@Sun.COM 						return (0);
24347887SLiane.Praza@Sun.COM 					else
24357887SLiane.Praza@Sun.COM 						return (-1);
24367887SLiane.Praza@Sun.COM 				}
24377887SLiane.Praza@Sun.COM 				continue;
24387887SLiane.Praza@Sun.COM 			} else {
24397887SLiane.Praza@Sun.COM 				assert(0);
24407887SLiane.Praza@Sun.COM 				abort();
24417887SLiane.Praza@Sun.COM 			}
24427887SLiane.Praza@Sun.COM 		}
24437887SLiane.Praza@Sun.COM 
24447887SLiane.Praza@Sun.COM 		/*
24457887SLiane.Praza@Sun.COM 		 * Discard pgs which don't exist at the right scoping.  This
24467887SLiane.Praza@Sun.COM 		 * check also makes sure that if we're looking at, for
24477887SLiane.Praza@Sun.COM 		 * example, svc:/system/svc/restarter:default, that we
24487887SLiane.Praza@Sun.COM 		 * don't hand back the same property groups twice.
24497887SLiane.Praza@Sun.COM 		 */
24507887SLiane.Praza@Sun.COM 		switch (t->pt_iter_last) {
24517887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_INST:
24527887SLiane.Praza@Sun.COM 			ret = check_target_match(pg_tmpl->pt_pg,
24537887SLiane.Praza@Sun.COM 			    SCF_TM_TARGET_THIS);
24547887SLiane.Praza@Sun.COM 			break;
24557887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_RESTARTER:
24567887SLiane.Praza@Sun.COM 			ret = check_target_match(pg_tmpl->pt_pg,
24577887SLiane.Praza@Sun.COM 			    SCF_TM_TARGET_DELEGATE);
24587887SLiane.Praza@Sun.COM 			break;
24597887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_GLOBAL:
24607887SLiane.Praza@Sun.COM 			ret = check_target_match(pg_tmpl->pt_pg,
24617887SLiane.Praza@Sun.COM 			    SCF_TM_TARGET_ALL);
24627887SLiane.Praza@Sun.COM 			break;
24637887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_NONE:
24647887SLiane.Praza@Sun.COM 		default:
24657887SLiane.Praza@Sun.COM 			assert(0);
24667887SLiane.Praza@Sun.COM 			abort();
24677887SLiane.Praza@Sun.COM 		}
24687887SLiane.Praza@Sun.COM 
24697887SLiane.Praza@Sun.COM 		if (ret != 0)
24707887SLiane.Praza@Sun.COM 			continue;
24717887SLiane.Praza@Sun.COM 
24727887SLiane.Praza@Sun.COM 		/*
24737887SLiane.Praza@Sun.COM 		 * If walking only required property groups, check if
24747887SLiane.Praza@Sun.COM 		 * the retrieved group is required.
24757887SLiane.Praza@Sun.COM 		 */
24767887SLiane.Praza@Sun.COM 		if (flags & SCF_PG_TMPL_FLAG_REQUIRED) {
24777887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_required(pg_tmpl, &required) == 0) {
24787887SLiane.Praza@Sun.COM 				if (required == 0)
24797887SLiane.Praza@Sun.COM 					continue;
24807887SLiane.Praza@Sun.COM 			} else {
24817887SLiane.Praza@Sun.COM 				return (-1);
24827887SLiane.Praza@Sun.COM 			}
24837887SLiane.Praza@Sun.COM 		}
24847887SLiane.Praza@Sun.COM 
24857887SLiane.Praza@Sun.COM 		/*
24867887SLiane.Praza@Sun.COM 		 * If type != NULL, check if type property matches.  If no
24877887SLiane.Praza@Sun.COM 		 * type property exists, consider it a match.
24887887SLiane.Praza@Sun.COM 		 */
24897887SLiane.Praza@Sun.COM 		if (type != NULL) {
24907887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_type(pg_tmpl, &tmpl_type) != -1) {
24917887SLiane.Praza@Sun.COM 				if (strcmp(tmpl_type, SCF_TMPL_WILDCARD)
24927887SLiane.Praza@Sun.COM 				    == 0 || strcmp(type, tmpl_type) == 0) {
24937887SLiane.Praza@Sun.COM 					free(tmpl_type);
24947887SLiane.Praza@Sun.COM 					break;
24957887SLiane.Praza@Sun.COM 				}
24967887SLiane.Praza@Sun.COM 				free(tmpl_type);
24977887SLiane.Praza@Sun.COM 			} else if (scf_error() == SCF_ERROR_NOT_FOUND ||
24987887SLiane.Praza@Sun.COM 			    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED ||
24997887SLiane.Praza@Sun.COM 			    scf_error() == SCF_ERROR_TYPE_MISMATCH) {
25007887SLiane.Praza@Sun.COM 				break;
25017887SLiane.Praza@Sun.COM 			} else {
25027887SLiane.Praza@Sun.COM 				return (-1);
25037887SLiane.Praza@Sun.COM 			}
25047887SLiane.Praza@Sun.COM 		} else {
25057887SLiane.Praza@Sun.COM 			break;
25067887SLiane.Praza@Sun.COM 		}
25077887SLiane.Praza@Sun.COM 	}
25087887SLiane.Praza@Sun.COM 
25097887SLiane.Praza@Sun.COM 	return (1);
25107887SLiane.Praza@Sun.COM 
25117887SLiane.Praza@Sun.COM fail_non_populated:
25127887SLiane.Praza@Sun.COM 	scf_service_destroy(svc);
25137887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
25147887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
25157887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
25167887SLiane.Praza@Sun.COM 	return (-1);
25177887SLiane.Praza@Sun.COM }
25187887SLiane.Praza@Sun.COM 
25197887SLiane.Praza@Sun.COM void
scf_tmpl_pg_destroy(scf_pg_tmpl_t * t)25207887SLiane.Praza@Sun.COM scf_tmpl_pg_destroy(scf_pg_tmpl_t *t)
25217887SLiane.Praza@Sun.COM {
25227887SLiane.Praza@Sun.COM 	if (t == NULL)
25237887SLiane.Praza@Sun.COM 		return;
25247887SLiane.Praza@Sun.COM 
25257887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->pt_pg);
25267887SLiane.Praza@Sun.COM 	scf_instance_destroy(t->pt_inst);
25277887SLiane.Praza@Sun.COM 	if (t->pt_inst != t->pt_orig_inst)
25287887SLiane.Praza@Sun.COM 		scf_instance_destroy(t->pt_orig_inst);
25297887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(t->pt_snap);
25307887SLiane.Praza@Sun.COM 	scf_service_destroy(t->pt_orig_svc);
25317887SLiane.Praza@Sun.COM 	if (t->pt_svc != t->pt_orig_svc)
25327887SLiane.Praza@Sun.COM 		scf_service_destroy(t->pt_svc);
25337887SLiane.Praza@Sun.COM 	scf_iter_destroy(t->pt_iter);
25347887SLiane.Praza@Sun.COM 	free(t);
25357887SLiane.Praza@Sun.COM }
25367887SLiane.Praza@Sun.COM 
25377887SLiane.Praza@Sun.COM void
scf_tmpl_pg_reset(scf_pg_tmpl_t * t)25387887SLiane.Praza@Sun.COM scf_tmpl_pg_reset(scf_pg_tmpl_t *t)
25397887SLiane.Praza@Sun.COM {
25407887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->pt_pg);
25417887SLiane.Praza@Sun.COM 	t->pt_pg = NULL;
25427887SLiane.Praza@Sun.COM 
25437887SLiane.Praza@Sun.COM 	scf_instance_destroy(t->pt_inst);
25447887SLiane.Praza@Sun.COM 	if (t->pt_inst != t->pt_orig_inst)
25457887SLiane.Praza@Sun.COM 		scf_instance_destroy(t->pt_orig_inst);
25467887SLiane.Praza@Sun.COM 	t->pt_inst = NULL;
25477887SLiane.Praza@Sun.COM 	t->pt_orig_inst = NULL;
25487887SLiane.Praza@Sun.COM 
25497887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(t->pt_snap);
25507887SLiane.Praza@Sun.COM 	t->pt_snap = NULL;
25517887SLiane.Praza@Sun.COM 
25527887SLiane.Praza@Sun.COM 	scf_service_destroy(t->pt_orig_svc);
25537887SLiane.Praza@Sun.COM 	if (t->pt_svc != t->pt_orig_svc)
25547887SLiane.Praza@Sun.COM 		scf_service_destroy(t->pt_svc);
25557887SLiane.Praza@Sun.COM 	t->pt_orig_svc = NULL;
25567887SLiane.Praza@Sun.COM 	t->pt_svc = NULL;
25577887SLiane.Praza@Sun.COM 
25587887SLiane.Praza@Sun.COM 	scf_iter_destroy(t->pt_iter);
25597887SLiane.Praza@Sun.COM 	t->pt_iter = NULL;
25607887SLiane.Praza@Sun.COM 
25617887SLiane.Praza@Sun.COM 	t->pt_populated = 0;
25627887SLiane.Praza@Sun.COM 	t->pt_is_iter = 0;
25637887SLiane.Praza@Sun.COM 	t->pt_iter_last = 0;
25647887SLiane.Praza@Sun.COM 
25657887SLiane.Praza@Sun.COM 	/* Do not reset t->pt_h. */
25667887SLiane.Praza@Sun.COM }
25677887SLiane.Praza@Sun.COM 
25687887SLiane.Praza@Sun.COM /*
25697887SLiane.Praza@Sun.COM  * int scf_tmpl_get_by_prop()
25707887SLiane.Praza@Sun.COM  *
25717887SLiane.Praza@Sun.COM  * Get the property template given a property group template and property
25727887SLiane.Praza@Sun.COM  * name.  No flags are currently defined for this function.
25737887SLiane.Praza@Sun.COM  *
25747887SLiane.Praza@Sun.COM  * Returns NULL on failure, and sets scf_error():
25757887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
25767887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
25777887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
25787887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
25797887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
25807887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
25817887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
25827887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
25837887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
25847887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
25857887SLiane.Praza@Sun.COM  *     Template object matching property doesn't exist in the repository.
25867887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
25877887SLiane.Praza@Sun.COM  *     Matching template object is the wrong type in the repository.
25887887SLiane.Praza@Sun.COM  */
25897887SLiane.Praza@Sun.COM int
scf_tmpl_get_by_prop(scf_pg_tmpl_t * t,const char * prop,scf_prop_tmpl_t * prop_tmpl,int flags)25907887SLiane.Praza@Sun.COM scf_tmpl_get_by_prop(scf_pg_tmpl_t *t, const char *prop,
25917887SLiane.Praza@Sun.COM     scf_prop_tmpl_t *prop_tmpl, int flags)
25927887SLiane.Praza@Sun.COM {
25937887SLiane.Praza@Sun.COM 	char *tmpl_prop_name;
25947887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
25957887SLiane.Praza@Sun.COM 	char *pg_type;
25967887SLiane.Praza@Sun.COM 	int found = 0;
25977887SLiane.Praza@Sun.COM 
25987887SLiane.Praza@Sun.COM 	if (flags != 0) {
25997887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
26007887SLiane.Praza@Sun.COM 		return (-1);
26017887SLiane.Praza@Sun.COM 	}
26027887SLiane.Praza@Sun.COM 
26037887SLiane.Praza@Sun.COM 	scf_tmpl_prop_reset(prop_tmpl);
26047887SLiane.Praza@Sun.COM 	if ((pg = scf_pg_create(scf_pg_handle(t->pt_pg))) == NULL)
26057887SLiane.Praza@Sun.COM 		return (-1);
26067887SLiane.Praza@Sun.COM 
26077887SLiane.Praza@Sun.COM 	tmpl_prop_name = _tmpl_prop_name(prop, t);
26087887SLiane.Praza@Sun.COM 	if (tmpl_prop_name == NULL) {
26097887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
26107887SLiane.Praza@Sun.COM 		return (-1);
26117887SLiane.Praza@Sun.COM 	}
26127887SLiane.Praza@Sun.COM 
26137887SLiane.Praza@Sun.COM 	if (_get_pg(t->pt_svc, t->pt_inst, t->pt_snap,
26147887SLiane.Praza@Sun.COM 	    tmpl_prop_name, pg) != 0) {
26157887SLiane.Praza@Sun.COM 		if (!ismember(scf_error(), errors_server)) {
26167887SLiane.Praza@Sun.COM 			switch (scf_error()) {
26177887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
26187887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
26197887SLiane.Praza@Sun.COM 				break;
26207887SLiane.Praza@Sun.COM 
26217887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
26227887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
26237887SLiane.Praza@Sun.COM 			default:
26247887SLiane.Praza@Sun.COM 				assert(0);
26257887SLiane.Praza@Sun.COM 				abort();
26267887SLiane.Praza@Sun.COM 			}
26277887SLiane.Praza@Sun.COM 		}
26287887SLiane.Praza@Sun.COM 	} else {
26297887SLiane.Praza@Sun.COM 		/*
26307887SLiane.Praza@Sun.COM 		 * We've only found a template property group if the type
26317887SLiane.Praza@Sun.COM 		 * is correct.
26327887SLiane.Praza@Sun.COM 		 */
26337887SLiane.Praza@Sun.COM 		if ((pg_type = _scf_get_pg_type(pg)) != NULL &&
26347887SLiane.Praza@Sun.COM 		    strcmp(pg_type, SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0)
26357887SLiane.Praza@Sun.COM 			found++;
26367887SLiane.Praza@Sun.COM 		else
26377887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TYPE_MISMATCH);
26387887SLiane.Praza@Sun.COM 
26397887SLiane.Praza@Sun.COM 
26407887SLiane.Praza@Sun.COM 		free(pg_type);
26417887SLiane.Praza@Sun.COM 	}
26427887SLiane.Praza@Sun.COM 
26437887SLiane.Praza@Sun.COM 	if (found == 0) {
26447887SLiane.Praza@Sun.COM 		scf_pg_destroy(pg);
26457887SLiane.Praza@Sun.COM 		free(tmpl_prop_name);
26467887SLiane.Praza@Sun.COM 		return (-1);
26477887SLiane.Praza@Sun.COM 	}
26487887SLiane.Praza@Sun.COM 
26497887SLiane.Praza@Sun.COM 	prop_tmpl->prt_h = scf_pg_handle(t->pt_pg);
26507887SLiane.Praza@Sun.COM 	prop_tmpl->prt_t = t;
26517887SLiane.Praza@Sun.COM 	prop_tmpl->prt_pg = pg;
26527887SLiane.Praza@Sun.COM 	prop_tmpl->prt_pg_name = tmpl_prop_name;
26537887SLiane.Praza@Sun.COM 	prop_tmpl->prt_populated = 1;
26547887SLiane.Praza@Sun.COM 
26557887SLiane.Praza@Sun.COM 	return (0);
26567887SLiane.Praza@Sun.COM }
26577887SLiane.Praza@Sun.COM 
26587887SLiane.Praza@Sun.COM /*
26597887SLiane.Praza@Sun.COM  * scf_prop_tmpl_t *scf_tmpl_prop_create(scf_handle_t *);
26607887SLiane.Praza@Sun.COM  *
26617887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT, or
26627887SLiane.Praza@Sun.COM  * _NO_MEMORY.
26637887SLiane.Praza@Sun.COM  */
26647887SLiane.Praza@Sun.COM scf_prop_tmpl_t *
scf_tmpl_prop_create(scf_handle_t * handle)26657887SLiane.Praza@Sun.COM scf_tmpl_prop_create(scf_handle_t *handle)
26667887SLiane.Praza@Sun.COM {
26677887SLiane.Praza@Sun.COM 	scf_prop_tmpl_t *pt;
26687887SLiane.Praza@Sun.COM 
26697887SLiane.Praza@Sun.COM 	if (handle == NULL) {
26707887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
26717887SLiane.Praza@Sun.COM 		return (NULL);
26727887SLiane.Praza@Sun.COM 	}
26737887SLiane.Praza@Sun.COM 	pt = calloc(1, sizeof (scf_prop_tmpl_t));
26747887SLiane.Praza@Sun.COM 	if (pt == NULL)
26757887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
26767887SLiane.Praza@Sun.COM 	else
26777887SLiane.Praza@Sun.COM 		pt->prt_h = handle;
26787887SLiane.Praza@Sun.COM 
26797887SLiane.Praza@Sun.COM 	return (pt);
26807887SLiane.Praza@Sun.COM }
26817887SLiane.Praza@Sun.COM 
26827887SLiane.Praza@Sun.COM /*
26837887SLiane.Praza@Sun.COM  * int scf_tmpl_iter_props()
26847887SLiane.Praza@Sun.COM  *
26857887SLiane.Praza@Sun.COM  * Iterates over all property templates defined in the specified property
26867887SLiane.Praza@Sun.COM  * group template.  The iterator state is stored on the property template
26877887SLiane.Praza@Sun.COM  * data structure, and the data structure should be allocated with
26887887SLiane.Praza@Sun.COM  * scf_tmpl_prop_create().  To continue the iteration, the previously
26897887SLiane.Praza@Sun.COM  * returned structure should be passed in as an argument to this function.
26907887SLiane.Praza@Sun.COM  * flags can include SCF_PROP_TMPL_FLAG_REQUIRED.  The function returns
26917887SLiane.Praza@Sun.COM  * 1 when a result was found, and 0 when the iteration is complete.
26927887SLiane.Praza@Sun.COM  *
26937887SLiane.Praza@Sun.COM  * Returns -1 on failure, and sets scf_error():
26947887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
26957887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
26967887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
26977887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
26987887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
26997887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
27007887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
27017887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
27027887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
27037887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
27047887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
27057887SLiane.Praza@Sun.COM  *     Template data is invalid.  One of the property templates in this
27067887SLiane.Praza@Sun.COM  *     pg_tmpl is malformed.
27077887SLiane.Praza@Sun.COM  */
27087887SLiane.Praza@Sun.COM int
scf_tmpl_iter_props(scf_pg_tmpl_t * t,scf_prop_tmpl_t * pt,int flags)27097887SLiane.Praza@Sun.COM scf_tmpl_iter_props(scf_pg_tmpl_t *t, scf_prop_tmpl_t *pt, int flags)
27107887SLiane.Praza@Sun.COM {
27117887SLiane.Praza@Sun.COM 	scf_prop_tmpl_t *prop_tmpl;
27127887SLiane.Praza@Sun.COM 	char *pg_pat;
27137887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
27147887SLiane.Praza@Sun.COM 	int err;
27157887SLiane.Praza@Sun.COM 	int ret;
27167887SLiane.Praza@Sun.COM 	ssize_t size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
27177887SLiane.Praza@Sun.COM 	uint8_t required;
27187887SLiane.Praza@Sun.COM 	scf_handle_t *h;
27197887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
27207887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
27217887SLiane.Praza@Sun.COM 
27227887SLiane.Praza@Sun.COM 	assert(size != 0);
27237887SLiane.Praza@Sun.COM 	if (t == NULL || pt == NULL) {
27247887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
27257887SLiane.Praza@Sun.COM 		return (-1);
27267887SLiane.Praza@Sun.COM 	}
27277887SLiane.Praza@Sun.COM 
27287887SLiane.Praza@Sun.COM 	assert(t->pt_inst == NULL || t->pt_svc == NULL);
27297887SLiane.Praza@Sun.COM 	assert(t->pt_inst != NULL || t->pt_svc != NULL);
27307887SLiane.Praza@Sun.COM 
27317887SLiane.Praza@Sun.COM 	if ((pg_name = malloc(size)) == NULL) {
27327887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
27337887SLiane.Praza@Sun.COM 		return (-1);
27347887SLiane.Praza@Sun.COM 	}
27357887SLiane.Praza@Sun.COM 
27367887SLiane.Praza@Sun.COM 	if (pt->prt_populated == 0) {
27377887SLiane.Praza@Sun.COM 		if ((h = scf_pg_handle(t->pt_pg)) == NULL)
27387887SLiane.Praza@Sun.COM 			goto fail_non_populated;
27397887SLiane.Praza@Sun.COM 
27407887SLiane.Praza@Sun.COM 		if ((pg = scf_pg_create(h)) == NULL ||
27417887SLiane.Praza@Sun.COM 		    (iter = scf_iter_create(h)) == NULL)
27427887SLiane.Praza@Sun.COM 			goto fail_non_populated;
27437887SLiane.Praza@Sun.COM 
27447887SLiane.Praza@Sun.COM 		if (t->pt_inst != NULL)
27457887SLiane.Praza@Sun.COM 			err = scf_iter_instance_pgs_typed_composed(iter,
27467887SLiane.Praza@Sun.COM 			    t->pt_inst, t->pt_snap,
27477887SLiane.Praza@Sun.COM 			    SCF_GROUP_TEMPLATE_PROP_PATTERN);
27487887SLiane.Praza@Sun.COM 		else if (t->pt_svc != NULL)
27497887SLiane.Praza@Sun.COM 			err = scf_iter_service_pgs_typed(iter, t->pt_svc,
27507887SLiane.Praza@Sun.COM 			    SCF_GROUP_TEMPLATE_PROP_PATTERN);
27517887SLiane.Praza@Sun.COM 
27527887SLiane.Praza@Sun.COM 		if (err != 0) {
27537887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
27547887SLiane.Praza@Sun.COM 				goto fail_non_populated;
27557887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
27567887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
27577887SLiane.Praza@Sun.COM 				goto fail_non_populated;
27587887SLiane.Praza@Sun.COM 
27597887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
27607887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
27617887SLiane.Praza@Sun.COM 			default:
27627887SLiane.Praza@Sun.COM 				assert(0);
27637887SLiane.Praza@Sun.COM 				abort();
27647887SLiane.Praza@Sun.COM 			}
27657887SLiane.Praza@Sun.COM 
27667887SLiane.Praza@Sun.COM 		}
27677887SLiane.Praza@Sun.COM 		prop_tmpl = pt;
27687887SLiane.Praza@Sun.COM 		prop_tmpl->prt_t = t;
27697887SLiane.Praza@Sun.COM 		prop_tmpl->prt_populated = 1;
27707887SLiane.Praza@Sun.COM 		prop_tmpl->prt_pg = pg;
27717887SLiane.Praza@Sun.COM 		prop_tmpl->prt_iter = iter;
27727887SLiane.Praza@Sun.COM 	} else {
27737887SLiane.Praza@Sun.COM 		prop_tmpl = pt;
27747887SLiane.Praza@Sun.COM 	}
27757887SLiane.Praza@Sun.COM 
27767887SLiane.Praza@Sun.COM 	while ((err = scf_iter_next_pg(prop_tmpl->prt_iter,
27777887SLiane.Praza@Sun.COM 	    prop_tmpl->prt_pg)) > 0) {
27787887SLiane.Praza@Sun.COM 		/*
27797887SLiane.Praza@Sun.COM 		 * Check if the name matches the appropriate property
27807887SLiane.Praza@Sun.COM 		 * group template name.
27817887SLiane.Praza@Sun.COM 		 */
27827887SLiane.Praza@Sun.COM 		pg_pat = _scf_read_single_astring_from_pg(prop_tmpl->prt_pg,
27837887SLiane.Praza@Sun.COM 		    SCF_PROPERTY_TM_PG_PATTERN);
27847887SLiane.Praza@Sun.COM 		if (pg_pat == NULL) {
27857887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
27867887SLiane.Praza@Sun.COM 				uu_free(pg_name);
27877887SLiane.Praza@Sun.COM 				return (-1);
27887887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
27897887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
27907887SLiane.Praza@Sun.COM 				continue;
27917887SLiane.Praza@Sun.COM 
27927887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
27937887SLiane.Praza@Sun.COM 			case SCF_ERROR_TYPE_MISMATCH:
27947887SLiane.Praza@Sun.COM 				(void) scf_set_error(
27957887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
27967887SLiane.Praza@Sun.COM 				free(pg_name);
27977887SLiane.Praza@Sun.COM 				return (-1);
27987887SLiane.Praza@Sun.COM 
27997887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
28007887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
28017887SLiane.Praza@Sun.COM 			default:
28027887SLiane.Praza@Sun.COM 				assert(0);
28037887SLiane.Praza@Sun.COM 				abort();
28047887SLiane.Praza@Sun.COM 			}
28057887SLiane.Praza@Sun.COM 		}
28067887SLiane.Praza@Sun.COM 		if ((ret = scf_pg_get_name(t->pt_pg, pg_name, size)) <= 0) {
28077887SLiane.Praza@Sun.COM 			free(pg_pat);
28087887SLiane.Praza@Sun.COM 			if (ret == 0)
28097887SLiane.Praza@Sun.COM 				continue;
28107887SLiane.Praza@Sun.COM 
28117887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
28127887SLiane.Praza@Sun.COM 				free(pg_name);
28137887SLiane.Praza@Sun.COM 				return (-1);
28147887SLiane.Praza@Sun.COM 			} else {
28157887SLiane.Praza@Sun.COM 				assert(0);
28167887SLiane.Praza@Sun.COM 				abort();
28177887SLiane.Praza@Sun.COM 			}
28187887SLiane.Praza@Sun.COM 		}
28197887SLiane.Praza@Sun.COM 		if (strcmp(pg_pat, pg_name) != 0) {
28207887SLiane.Praza@Sun.COM 			free(pg_pat);
28217887SLiane.Praza@Sun.COM 			continue;
28227887SLiane.Praza@Sun.COM 		}
28237887SLiane.Praza@Sun.COM 		free(pg_pat);
28247887SLiane.Praza@Sun.COM 
28257887SLiane.Praza@Sun.COM 		/*
28267887SLiane.Praza@Sun.COM 		 * If walking only required properties, check if
28277887SLiane.Praza@Sun.COM 		 * the retrieved property is required.
28287887SLiane.Praza@Sun.COM 		 */
28297887SLiane.Praza@Sun.COM 		if (flags & SCF_PROP_TMPL_FLAG_REQUIRED) {
28307887SLiane.Praza@Sun.COM 			if (scf_tmpl_prop_required(prop_tmpl, &required) == 0) {
28317887SLiane.Praza@Sun.COM 				if (required == 0)
28327887SLiane.Praza@Sun.COM 					continue;
28337887SLiane.Praza@Sun.COM 			} else {
28347887SLiane.Praza@Sun.COM 				free(pg_name);
28357887SLiane.Praza@Sun.COM 				return (-1);
28367887SLiane.Praza@Sun.COM 			}
28377887SLiane.Praza@Sun.COM 		}
28387887SLiane.Praza@Sun.COM 		free(pg_name);
28397887SLiane.Praza@Sun.COM 		return (0);
28407887SLiane.Praza@Sun.COM 	}
28417887SLiane.Praza@Sun.COM 
28427887SLiane.Praza@Sun.COM 	if (err == -1) {
28437887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
28447887SLiane.Praza@Sun.COM 			free(pg_name);
28457887SLiane.Praza@Sun.COM 			return (-1);
28467887SLiane.Praza@Sun.COM 		} else {
28477887SLiane.Praza@Sun.COM 			assert(0);
28487887SLiane.Praza@Sun.COM 			abort();
28497887SLiane.Praza@Sun.COM 		}
28507887SLiane.Praza@Sun.COM 	} else if (err == 0)  {
28517887SLiane.Praza@Sun.COM 		scf_iter_destroy(prop_tmpl->prt_iter);
28527887SLiane.Praza@Sun.COM 		prop_tmpl->prt_iter = NULL;
28537887SLiane.Praza@Sun.COM 		prop_tmpl->prt_populated = 0;
28547887SLiane.Praza@Sun.COM 	}
28557887SLiane.Praza@Sun.COM 	free(pg_name);
28567887SLiane.Praza@Sun.COM 
28577887SLiane.Praza@Sun.COM 	return (1);
28587887SLiane.Praza@Sun.COM 
28597887SLiane.Praza@Sun.COM fail_non_populated:
28607887SLiane.Praza@Sun.COM 	free(pg_name);
28617887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
28627887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
28637887SLiane.Praza@Sun.COM 	return (-1);
28647887SLiane.Praza@Sun.COM }
28657887SLiane.Praza@Sun.COM 
28667887SLiane.Praza@Sun.COM void
scf_tmpl_prop_destroy(scf_prop_tmpl_t * t)28677887SLiane.Praza@Sun.COM scf_tmpl_prop_destroy(scf_prop_tmpl_t *t)
28687887SLiane.Praza@Sun.COM {
28697887SLiane.Praza@Sun.COM 	if (t == NULL)
28707887SLiane.Praza@Sun.COM 		return;
28717887SLiane.Praza@Sun.COM 
28727887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->prt_pg);
28737887SLiane.Praza@Sun.COM 	free(t->prt_pg_name);
28747887SLiane.Praza@Sun.COM 	free(t->prt_iter);
28757887SLiane.Praza@Sun.COM 	free(t);
28767887SLiane.Praza@Sun.COM }
28777887SLiane.Praza@Sun.COM 
28787887SLiane.Praza@Sun.COM void
scf_tmpl_prop_reset(scf_prop_tmpl_t * t)28797887SLiane.Praza@Sun.COM scf_tmpl_prop_reset(scf_prop_tmpl_t *t)
28807887SLiane.Praza@Sun.COM {
28817887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->prt_pg);
28827887SLiane.Praza@Sun.COM 	t->prt_pg = NULL;
28837887SLiane.Praza@Sun.COM 
28847887SLiane.Praza@Sun.COM 	free(t->prt_pg_name);
28857887SLiane.Praza@Sun.COM 	t->prt_pg_name = NULL;
28867887SLiane.Praza@Sun.COM 
28877887SLiane.Praza@Sun.COM 	free(t->prt_iter);
28887887SLiane.Praza@Sun.COM 	t->prt_iter = NULL;
28897887SLiane.Praza@Sun.COM 
28907887SLiane.Praza@Sun.COM 	t->prt_populated = 0;
28917887SLiane.Praza@Sun.COM 	t->prt_h = NULL;
28927887SLiane.Praza@Sun.COM 	t->prt_t = NULL;
28937887SLiane.Praza@Sun.COM }
28947887SLiane.Praza@Sun.COM 
28957887SLiane.Praza@Sun.COM /*
28967887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
28977887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
28987887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
28997887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
29007887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
29017887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
29027887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
29037887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
29047887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
29057887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
29067887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
29077887SLiane.Praza@Sun.COM  *     The name of the template property group (the pname property) has
29087887SLiane.Praza@Sun.COM  *     an improper repository format and is not type astring or has
29097887SLiane.Praza@Sun.COM  *     more than one value.
29107887SLiane.Praza@Sun.COM  */
29117887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_pg_name(const scf_pg_tmpl_t * t,char ** out)29127887SLiane.Praza@Sun.COM scf_tmpl_pg_name(const scf_pg_tmpl_t *t, char **out)
29137887SLiane.Praza@Sun.COM {
29147887SLiane.Praza@Sun.COM 	return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_NAME, out));
29157887SLiane.Praza@Sun.COM }
29167887SLiane.Praza@Sun.COM 
29177887SLiane.Praza@Sun.COM /*
29187887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed
29197887SLiane.Praza@Sun.COM  *
29207887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
29217887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
29227887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
29237887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
29247887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
29257887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
29267887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
29277887SLiane.Praza@Sun.COM  *     name not a valid property name
29287887SLiane.Praza@Sun.COM  *     name and locale are too long to make a property name
29297887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
29307887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
29317887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
29327887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
29337887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
29347887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
29357887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
29367887SLiane.Praza@Sun.COM  */
29377887SLiane.Praza@Sun.COM static char *
_read_localized_astring_from_pg(scf_propertygroup_t * pg,const char * name,const char * locale)29387887SLiane.Praza@Sun.COM _read_localized_astring_from_pg(scf_propertygroup_t *pg, const char *name,
29397887SLiane.Praza@Sun.COM     const char *locale)
29407887SLiane.Praza@Sun.COM {
29417887SLiane.Praza@Sun.COM 	char *str;
29427887SLiane.Praza@Sun.COM 	char *lname_prop;
29437887SLiane.Praza@Sun.COM 
29447887SLiane.Praza@Sun.COM 	str = _add_locale_to_name(name, locale);
29457887SLiane.Praza@Sun.COM 	if (str == NULL)
29467887SLiane.Praza@Sun.COM 		return (NULL);
29477887SLiane.Praza@Sun.COM 	lname_prop = _scf_read_single_astring_from_pg(pg, str);
29487887SLiane.Praza@Sun.COM 	if (lname_prop == NULL) {
29497887SLiane.Praza@Sun.COM 		free(str);
29507887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND)
29517887SLiane.Praza@Sun.COM 			return (NULL);
29527887SLiane.Praza@Sun.COM 		str = _add_locale_to_name(name, "C");
29537887SLiane.Praza@Sun.COM 		if (str == NULL)
29547887SLiane.Praza@Sun.COM 			return (NULL);
29557887SLiane.Praza@Sun.COM 		lname_prop = _scf_read_single_astring_from_pg(pg, str);
29567887SLiane.Praza@Sun.COM 	}
29577887SLiane.Praza@Sun.COM 	free(str);
29587887SLiane.Praza@Sun.COM 	if (lname_prop == NULL) {
29597887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_TYPE_MISMATCH ||
29607887SLiane.Praza@Sun.COM 		    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
29617887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
29627887SLiane.Praza@Sun.COM 	}
29637887SLiane.Praza@Sun.COM 	return (lname_prop);
29647887SLiane.Praza@Sun.COM }
29657887SLiane.Praza@Sun.COM 
29667887SLiane.Praza@Sun.COM /*
29677887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed
29687887SLiane.Praza@Sun.COM  *
29697887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
29707887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
29717887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
29727887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
29737887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
29747887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
29757887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
29767887SLiane.Praza@Sun.COM  *     locale is too long to make a valid property name
29777887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
29787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
29797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
29807887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
29817887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
29827887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
29837887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
29847887SLiane.Praza@Sun.COM  */
29857887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_pg_common_name(const scf_pg_tmpl_t * t,const char * locale,char ** out)29867887SLiane.Praza@Sun.COM scf_tmpl_pg_common_name(const scf_pg_tmpl_t *t, const char *locale, char **out)
29877887SLiane.Praza@Sun.COM {
29887887SLiane.Praza@Sun.COM 	assert(out != NULL);
29897887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->pt_pg,
29907887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL)
29917887SLiane.Praza@Sun.COM 		return (-1);
29927887SLiane.Praza@Sun.COM 
29937887SLiane.Praza@Sun.COM 	return (strlen(*out));
29947887SLiane.Praza@Sun.COM }
29957887SLiane.Praza@Sun.COM 
29967887SLiane.Praza@Sun.COM /*
29977887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed
29987887SLiane.Praza@Sun.COM  *
29997887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
30007887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
30017887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
30027887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
30037887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
30047887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
30057887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
30067887SLiane.Praza@Sun.COM  *     locale is too long to make a valid property name
30077887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
30087887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
30097887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
30107887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
30117887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
30127887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
30137887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
30147887SLiane.Praza@Sun.COM  */
30157887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_pg_description(const scf_pg_tmpl_t * t,const char * locale,char ** out)30167887SLiane.Praza@Sun.COM scf_tmpl_pg_description(const scf_pg_tmpl_t *t, const char *locale, char **out)
30177887SLiane.Praza@Sun.COM {
30187887SLiane.Praza@Sun.COM 	assert(out != NULL);
30197887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->pt_pg,
30207887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL)
30217887SLiane.Praza@Sun.COM 		return (-1);
30227887SLiane.Praza@Sun.COM 
30237887SLiane.Praza@Sun.COM 	return (strlen(*out));
30247887SLiane.Praza@Sun.COM }
30257887SLiane.Praza@Sun.COM 
30267887SLiane.Praza@Sun.COM /*
30277887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
30287887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
30297887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
30307887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
30317887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
30327887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
30337887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
30347887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
30357887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
30367887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
30377887SLiane.Praza@Sun.COM  *     'type' property doesn't exist or exists and has no value.
30387887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
30397887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
30407887SLiane.Praza@Sun.COM  *     'type' property is not SCF_TYPE_ASTRING or has more than one value.
30417887SLiane.Praza@Sun.COM  */
30427887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_pg_type(const scf_pg_tmpl_t * t,char ** out)30437887SLiane.Praza@Sun.COM scf_tmpl_pg_type(const scf_pg_tmpl_t *t, char **out)
30447887SLiane.Praza@Sun.COM {
30457887SLiane.Praza@Sun.COM 	return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_TYPE, out));
30467887SLiane.Praza@Sun.COM }
30477887SLiane.Praza@Sun.COM 
30487887SLiane.Praza@Sun.COM /*
30497887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
30507887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
30517887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
30527887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
30537887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
30547887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
30557887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
30567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
30577887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
30587887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
30597887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
30607887SLiane.Praza@Sun.COM  *     required property is not SCF_TYPE_BOOLEAN or has more than one value.
30617887SLiane.Praza@Sun.COM  */
30627887SLiane.Praza@Sun.COM int
scf_tmpl_pg_required(const scf_pg_tmpl_t * t,uint8_t * out)30637887SLiane.Praza@Sun.COM scf_tmpl_pg_required(const scf_pg_tmpl_t *t, uint8_t *out)
30647887SLiane.Praza@Sun.COM {
30657887SLiane.Praza@Sun.COM 
30667887SLiane.Praza@Sun.COM 	if (_read_single_boolean_from_pg(t->pt_pg, SCF_PROPERTY_TM_REQUIRED,
30677887SLiane.Praza@Sun.COM 	    out) == -1) {
30687887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
30697887SLiane.Praza@Sun.COM 			return (-1);
30707887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
30717887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
30727887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
30737887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
30747887SLiane.Praza@Sun.COM 			return (-1);
30757887SLiane.Praza@Sun.COM 
30767887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
30777887SLiane.Praza@Sun.COM 			*out = 0;
30787887SLiane.Praza@Sun.COM 			return (0);
30797887SLiane.Praza@Sun.COM 
30807887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
30817887SLiane.Praza@Sun.COM 		default:
30827887SLiane.Praza@Sun.COM 			assert(0);
30837887SLiane.Praza@Sun.COM 			abort();
30847887SLiane.Praza@Sun.COM 		}
30857887SLiane.Praza@Sun.COM 	}
30867887SLiane.Praza@Sun.COM 
30877887SLiane.Praza@Sun.COM 	return (0);
30887887SLiane.Praza@Sun.COM }
30897887SLiane.Praza@Sun.COM 
30907887SLiane.Praza@Sun.COM /*
30917887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
30927887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
30937887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
30947887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
30957887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
30967887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
30977887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
30987887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
30997887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
31007887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
31017887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
31027887SLiane.Praza@Sun.COM  *     target property is not SCF_TYPE_ASTRING or has more than one value.
31037887SLiane.Praza@Sun.COM  */
31047887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_pg_target(const scf_pg_tmpl_t * t,char ** out)31057887SLiane.Praza@Sun.COM scf_tmpl_pg_target(const scf_pg_tmpl_t *t, char **out)
31067887SLiane.Praza@Sun.COM {
31077887SLiane.Praza@Sun.COM 	*out = _scf_read_single_astring_from_pg(t->pt_pg,
31087887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TARGET);
31097887SLiane.Praza@Sun.COM 
31107887SLiane.Praza@Sun.COM 	if (*out == NULL) {
31117887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
31127887SLiane.Praza@Sun.COM 			return (-1);
31137887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
31147887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
31157887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
31167887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
31177887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
31187887SLiane.Praza@Sun.COM 			return (-1);
31197887SLiane.Praza@Sun.COM 
31207887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
31217887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
31227887SLiane.Praza@Sun.COM 		default:
31237887SLiane.Praza@Sun.COM 			assert(0);
31247887SLiane.Praza@Sun.COM 			abort();
31257887SLiane.Praza@Sun.COM 		}
31267887SLiane.Praza@Sun.COM 	}
31277887SLiane.Praza@Sun.COM 
31287887SLiane.Praza@Sun.COM 	return (strlen(*out));
31297887SLiane.Praza@Sun.COM }
31307887SLiane.Praza@Sun.COM 
31317887SLiane.Praza@Sun.COM /*
31327887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
31337887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
31347887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
31357887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
31367887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
31377887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
31387887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
31397887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
31407887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
31417887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
31427887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
31437887SLiane.Praza@Sun.COM  */
31447887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_prop_name(const scf_prop_tmpl_t * t,char ** out)31457887SLiane.Praza@Sun.COM scf_tmpl_prop_name(const scf_prop_tmpl_t *t, char **out)
31467887SLiane.Praza@Sun.COM {
31477887SLiane.Praza@Sun.COM 	*out = _scf_read_single_astring_from_pg(t->prt_pg,
31487887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_NAME);
31497887SLiane.Praza@Sun.COM 
31507887SLiane.Praza@Sun.COM 	if (*out != NULL && *out[0] == '\0') {
31517887SLiane.Praza@Sun.COM 		free(*out);
31527887SLiane.Praza@Sun.COM 		*out = NULL;
31537887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
31547887SLiane.Praza@Sun.COM 	}
31557887SLiane.Praza@Sun.COM 	if (*out == NULL) {
31567887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
31577887SLiane.Praza@Sun.COM 			return (-1);
31587887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
31597887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
31607887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
31617887SLiane.Praza@Sun.COM 		case SCF_ERROR_TEMPLATE_INVALID:
31627887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
31637887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
31647887SLiane.Praza@Sun.COM 			return (-1);
31657887SLiane.Praza@Sun.COM 
31667887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
31677887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
31687887SLiane.Praza@Sun.COM 		default:
31697887SLiane.Praza@Sun.COM 			assert(0);
31707887SLiane.Praza@Sun.COM 			abort();
31717887SLiane.Praza@Sun.COM 		}
31727887SLiane.Praza@Sun.COM 	}
31737887SLiane.Praza@Sun.COM 
31747887SLiane.Praza@Sun.COM 	return (strlen(*out));
31757887SLiane.Praza@Sun.COM }
31767887SLiane.Praza@Sun.COM 
31777887SLiane.Praza@Sun.COM /*
31787887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
31797887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
31807887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
31817887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
31827887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
31837887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
31847887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
31857887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
31867887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
31877887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
31887887SLiane.Praza@Sun.COM  *     'type' property doesn't exist or exists and has no value.
31897887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
31907887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
31917887SLiane.Praza@Sun.COM  *     'type' property is not SCF_TYPE_ASTRING, has more than one value,
31927887SLiane.Praza@Sun.COM  *     is SCF_TYPE_INVALID, or is the empty string.
31937887SLiane.Praza@Sun.COM  */
31947887SLiane.Praza@Sun.COM int
scf_tmpl_prop_type(const scf_prop_tmpl_t * t,scf_type_t * out)31957887SLiane.Praza@Sun.COM scf_tmpl_prop_type(const scf_prop_tmpl_t *t, scf_type_t *out)
31967887SLiane.Praza@Sun.COM {
31977887SLiane.Praza@Sun.COM 	char *type;
31987887SLiane.Praza@Sun.COM 
31997887SLiane.Praza@Sun.COM 	type = _scf_read_single_astring_from_pg(t->prt_pg,
32007887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TYPE);
32017887SLiane.Praza@Sun.COM 	if (type != NULL && type[0] == '\0') {
32027887SLiane.Praza@Sun.COM 		free(type);
32037887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
32047887SLiane.Praza@Sun.COM 		return (-1);
32057887SLiane.Praza@Sun.COM 	}
32067887SLiane.Praza@Sun.COM 	if (type == NULL) {
32077887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
32087887SLiane.Praza@Sun.COM 			return (-1);
32097887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
32107887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
32117887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
32127887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
32137887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
32147887SLiane.Praza@Sun.COM 
32157887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
32167887SLiane.Praza@Sun.COM 			return (-1);
32177887SLiane.Praza@Sun.COM 
32187887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
32197887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
32207887SLiane.Praza@Sun.COM 		default:
32217887SLiane.Praza@Sun.COM 			assert(0);
32227887SLiane.Praza@Sun.COM 			abort();
32237887SLiane.Praza@Sun.COM 		}
32247887SLiane.Praza@Sun.COM 	}
32257887SLiane.Praza@Sun.COM 
32267887SLiane.Praza@Sun.COM 	*out = scf_string_to_type(type);
32277887SLiane.Praza@Sun.COM 	free(type);
32287887SLiane.Praza@Sun.COM 
32297887SLiane.Praza@Sun.COM 	if (*out == SCF_TYPE_INVALID) {
32307887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
32317887SLiane.Praza@Sun.COM 		return (-1);
32327887SLiane.Praza@Sun.COM 	}
32337887SLiane.Praza@Sun.COM 
32347887SLiane.Praza@Sun.COM 	return (0);
32357887SLiane.Praza@Sun.COM }
32367887SLiane.Praza@Sun.COM 
32377887SLiane.Praza@Sun.COM /*
32387887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
32397887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
32407887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
32417887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
32427887SLiane.Praza@Sun.COM  *    Property group which represents t was deleted.
32437887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
32447887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
32457887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
32467887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
32477887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
32487887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
32497887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
32507887SLiane.Praza@Sun.COM  *     required property is not SCF_TYPE_ASTRING has more than one value.
32517887SLiane.Praza@Sun.COM  */
32527887SLiane.Praza@Sun.COM int
scf_tmpl_prop_required(const scf_prop_tmpl_t * t,uint8_t * out)32537887SLiane.Praza@Sun.COM scf_tmpl_prop_required(const scf_prop_tmpl_t *t, uint8_t *out)
32547887SLiane.Praza@Sun.COM {
32557887SLiane.Praza@Sun.COM 	if (_read_single_boolean_from_pg(t->prt_pg, SCF_PROPERTY_TM_REQUIRED,
32567887SLiane.Praza@Sun.COM 	    out) == -1) {
32577887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
32587887SLiane.Praza@Sun.COM 			return (-1);
32597887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
32607887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
32617887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
32627887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
32637887SLiane.Praza@Sun.COM 			return (-1);
32647887SLiane.Praza@Sun.COM 
32657887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
32667887SLiane.Praza@Sun.COM 			*out = 0;
32677887SLiane.Praza@Sun.COM 			return (0);
32687887SLiane.Praza@Sun.COM 
32697887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
32707887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
32717887SLiane.Praza@Sun.COM 		default:
32727887SLiane.Praza@Sun.COM 			assert(0);
32737887SLiane.Praza@Sun.COM 			abort();
32747887SLiane.Praza@Sun.COM 		}
32757887SLiane.Praza@Sun.COM 	}
32767887SLiane.Praza@Sun.COM 
32777887SLiane.Praza@Sun.COM 	return (0);
32787887SLiane.Praza@Sun.COM }
32797887SLiane.Praza@Sun.COM 
32807887SLiane.Praza@Sun.COM /*
32817887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
32827887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
32837887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
32847887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
32857887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
32867887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
32877887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
32887887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
32897887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
32907887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
32917887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
32927887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
32937887SLiane.Praza@Sun.COM  *     locale is too long to make a property name
32947887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
32957887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
32967887SLiane.Praza@Sun.COM  *     common_name property is not SCF_TYPE_ASTRING has more than one value.
32977887SLiane.Praza@Sun.COM  */
32987887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_prop_common_name(const scf_prop_tmpl_t * t,const char * locale,char ** out)32997887SLiane.Praza@Sun.COM scf_tmpl_prop_common_name(const scf_prop_tmpl_t *t, const char *locale,
33007887SLiane.Praza@Sun.COM     char **out)
33017887SLiane.Praza@Sun.COM {
33027887SLiane.Praza@Sun.COM 	assert(out != NULL);
33037887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->prt_pg,
33047887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL)
33057887SLiane.Praza@Sun.COM 		return (-1);
33067887SLiane.Praza@Sun.COM 
33077887SLiane.Praza@Sun.COM 	return (strlen(*out));
33087887SLiane.Praza@Sun.COM }
33097887SLiane.Praza@Sun.COM 
33107887SLiane.Praza@Sun.COM /*
33117887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
33127887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
33137887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
33147887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
33157887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
33167887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
33177887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
33187887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
33197887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
33207887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
33217887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
33227887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
33237887SLiane.Praza@Sun.COM  *     locale is too long to make a property name
33247887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
33257887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
33267887SLiane.Praza@Sun.COM  *     description property is not SCF_TYPE_ASTRING has more than one value.
33277887SLiane.Praza@Sun.COM  */
33287887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_prop_description(const scf_prop_tmpl_t * t,const char * locale,char ** out)33297887SLiane.Praza@Sun.COM scf_tmpl_prop_description(const scf_prop_tmpl_t *t, const char *locale,
33307887SLiane.Praza@Sun.COM     char **out)
33317887SLiane.Praza@Sun.COM {
33327887SLiane.Praza@Sun.COM 	assert(out != NULL);
33337887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->prt_pg,
33347887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL)
33357887SLiane.Praza@Sun.COM 		return (-1);
33367887SLiane.Praza@Sun.COM 
33377887SLiane.Praza@Sun.COM 	return (strlen(*out));
33387887SLiane.Praza@Sun.COM }
33397887SLiane.Praza@Sun.COM 
33407887SLiane.Praza@Sun.COM /*
33417887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
33427887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
33437887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
33447887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
33457887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
33467887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
33477887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
33487887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
33497887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
33507887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
33517887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
33527887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
33537887SLiane.Praza@Sun.COM  *     locale is too long to make a property name
33547887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
33557887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
33567887SLiane.Praza@Sun.COM  *     units property is not SCF_TYPE_ASTRING has more than one value.
33577887SLiane.Praza@Sun.COM  */
33587887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_prop_units(const scf_prop_tmpl_t * t,const char * locale,char ** out)33597887SLiane.Praza@Sun.COM scf_tmpl_prop_units(const scf_prop_tmpl_t *t, const char *locale, char **out)
33607887SLiane.Praza@Sun.COM {
33617887SLiane.Praza@Sun.COM 	assert(out != NULL);
33627887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->prt_pg,
33637887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_UNITS_PREFIX, locale)) == NULL)
33647887SLiane.Praza@Sun.COM 		return (-1);
33657887SLiane.Praza@Sun.COM 
33667887SLiane.Praza@Sun.COM 	return (strlen(*out));
33677887SLiane.Praza@Sun.COM }
33687887SLiane.Praza@Sun.COM 
33697887SLiane.Praza@Sun.COM /*
33707887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
33717887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
33727887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
33737887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
33747887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
33757887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
33767887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
33777887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
33787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
33797887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
33807887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
33817887SLiane.Praza@Sun.COM  *     visibility property is not SCF_TYPE_ASTRING has more than one value.
33827887SLiane.Praza@Sun.COM  */
33837887SLiane.Praza@Sun.COM int
scf_tmpl_prop_visibility(const scf_prop_tmpl_t * t,uint8_t * out)33847887SLiane.Praza@Sun.COM scf_tmpl_prop_visibility(const scf_prop_tmpl_t *t, uint8_t *out)
33857887SLiane.Praza@Sun.COM {
33867887SLiane.Praza@Sun.COM 	char *visibility;
33877887SLiane.Praza@Sun.COM 
33887887SLiane.Praza@Sun.COM 	visibility = _scf_read_single_astring_from_pg(t->prt_pg,
33897887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_VISIBILITY);
33907887SLiane.Praza@Sun.COM 	if (visibility == NULL) {
33917887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
33927887SLiane.Praza@Sun.COM 			return (-1);
33937887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
33947887SLiane.Praza@Sun.COM 		/* prop doesn't exist we take the default value */
33957887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
33967887SLiane.Praza@Sun.COM 			*out = SCF_TMPL_VISIBILITY_READWRITE;
33977887SLiane.Praza@Sun.COM 			return (0);
33987887SLiane.Praza@Sun.COM 
33997887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
34007887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
34017887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
34027887SLiane.Praza@Sun.COM 			return (-1);
34037887SLiane.Praza@Sun.COM 
34047887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
34057887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
34067887SLiane.Praza@Sun.COM 		default:
34077887SLiane.Praza@Sun.COM 			assert(0);
34087887SLiane.Praza@Sun.COM 			abort();
34097887SLiane.Praza@Sun.COM 		}
34107887SLiane.Praza@Sun.COM 	} else if (strcmp(visibility, SCF_TM_VISIBILITY_READWRITE) == 0) {
34117887SLiane.Praza@Sun.COM 		*out = SCF_TMPL_VISIBILITY_READWRITE;
34127887SLiane.Praza@Sun.COM 	} else if (strcmp(visibility, SCF_TM_VISIBILITY_HIDDEN) == 0) {
34137887SLiane.Praza@Sun.COM 		*out = SCF_TMPL_VISIBILITY_HIDDEN;
34147887SLiane.Praza@Sun.COM 	} else if (strcmp(visibility, SCF_TM_VISIBILITY_READONLY) == 0) {
34157887SLiane.Praza@Sun.COM 		*out = SCF_TMPL_VISIBILITY_READONLY;
34167887SLiane.Praza@Sun.COM 	} else {
34177887SLiane.Praza@Sun.COM 		free(visibility);
34187887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
34197887SLiane.Praza@Sun.COM 		return (-1);
34207887SLiane.Praza@Sun.COM 	}
34217887SLiane.Praza@Sun.COM 
34227887SLiane.Praza@Sun.COM 	free(visibility);
34237887SLiane.Praza@Sun.COM 	return (0);
34247887SLiane.Praza@Sun.COM }
34257887SLiane.Praza@Sun.COM 
34267887SLiane.Praza@Sun.COM /*
34277887SLiane.Praza@Sun.COM  * Return an allocated string containing the value that must be freed
34287887SLiane.Praza@Sun.COM  * with free().
34297887SLiane.Praza@Sun.COM  *
34307887SLiane.Praza@Sun.COM  * On error set scf_error() _NO_MEMORY, or _NOT_SET (val has not been set
34317887SLiane.Praza@Sun.COM  * to a value).
34327887SLiane.Praza@Sun.COM  */
34337887SLiane.Praza@Sun.COM static char *
_scf_value_get_as_string(scf_value_t * val)34347887SLiane.Praza@Sun.COM _scf_value_get_as_string(scf_value_t *val)
34357887SLiane.Praza@Sun.COM {
34367887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
34377887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
34387887SLiane.Praza@Sun.COM 
34397887SLiane.Praza@Sun.COM 	if (buf == NULL) {
34407887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
34417887SLiane.Praza@Sun.COM 	} else if (scf_value_get_as_string(val, buf, sz) == -1) {
34427887SLiane.Praza@Sun.COM 		free(buf);
34437887SLiane.Praza@Sun.COM 		buf = NULL;
34447887SLiane.Praza@Sun.COM 	}
34457887SLiane.Praza@Sun.COM 
34467887SLiane.Praza@Sun.COM 	return (buf);
34477887SLiane.Praza@Sun.COM }
34487887SLiane.Praza@Sun.COM 
34497887SLiane.Praza@Sun.COM /*
34507887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
34517887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
34527887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
34537887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
34547887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
34557887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
34567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
34577887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
34587887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
34597887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
34607887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
34617887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
34627887SLiane.Praza@Sun.COM  */
34637887SLiane.Praza@Sun.COM int
scf_tmpl_prop_cardinality(const scf_prop_tmpl_t * t,uint64_t * min,uint64_t * max)34647887SLiane.Praza@Sun.COM scf_tmpl_prop_cardinality(const scf_prop_tmpl_t *t, uint64_t *min,
34657887SLiane.Praza@Sun.COM     uint64_t *max)
34667887SLiane.Praza@Sun.COM {
34677887SLiane.Praza@Sun.COM 	scf_value_t *val_min = NULL;
34687887SLiane.Praza@Sun.COM 	scf_value_t *val_max = NULL;
34697887SLiane.Praza@Sun.COM 	int ret = 0;
34707887SLiane.Praza@Sun.COM 
34717887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(t->prt_pg,
34727887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CARDINALITY_MIN, &val_min) == 0) {
34737887SLiane.Praza@Sun.COM 		if (scf_value_get_count(val_min, min) < 0)
34747887SLiane.Praza@Sun.COM 			goto error;
34757887SLiane.Praza@Sun.COM 	} else {
34767887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND)
34777887SLiane.Praza@Sun.COM 			*min = 0;
34787887SLiane.Praza@Sun.COM 		else
34797887SLiane.Praza@Sun.COM 			goto error;
34807887SLiane.Praza@Sun.COM 	}
34817887SLiane.Praza@Sun.COM 
34827887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(t->prt_pg,
34837887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CARDINALITY_MAX, &val_max) == 0) {
34847887SLiane.Praza@Sun.COM 		if (scf_value_get_count(val_max, max) < 0)
34857887SLiane.Praza@Sun.COM 			goto error;
34867887SLiane.Praza@Sun.COM 	} else {
34877887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND)
34887887SLiane.Praza@Sun.COM 			*max = UINT64_MAX;
34897887SLiane.Praza@Sun.COM 		else
34907887SLiane.Praza@Sun.COM 			goto error;
34917887SLiane.Praza@Sun.COM 	}
34927887SLiane.Praza@Sun.COM 	goto cleanup;
34937887SLiane.Praza@Sun.COM 
34947887SLiane.Praza@Sun.COM error:
34957887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
34967887SLiane.Praza@Sun.COM 		ret = -1;
34977887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
34987887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
34997887SLiane.Praza@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
35007887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
35017887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
35027887SLiane.Praza@Sun.COM 
35037887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_FOUND:
35047887SLiane.Praza@Sun.COM 	case SCF_ERROR_TEMPLATE_INVALID:
35057887SLiane.Praza@Sun.COM 		ret = -1;
35067887SLiane.Praza@Sun.COM 		break;
35077887SLiane.Praza@Sun.COM 
35087887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
35097887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
35107887SLiane.Praza@Sun.COM 	default:
35117887SLiane.Praza@Sun.COM 		assert(0);
35127887SLiane.Praza@Sun.COM 		abort();
35137887SLiane.Praza@Sun.COM 	}
35147887SLiane.Praza@Sun.COM 
35157887SLiane.Praza@Sun.COM cleanup:
35167887SLiane.Praza@Sun.COM 	scf_value_destroy(val_min);
35177887SLiane.Praza@Sun.COM 	scf_value_destroy(val_max);
35187887SLiane.Praza@Sun.COM 
35197887SLiane.Praza@Sun.COM 	return (ret);
35207887SLiane.Praza@Sun.COM }
35217887SLiane.Praza@Sun.COM 
35227887SLiane.Praza@Sun.COM /*
35237887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
35247887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
35257887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
35267887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
35277887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
35287887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
35297887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
35307887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
35317887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
35327887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
35337887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
35347887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
35357887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
35367887SLiane.Praza@Sun.COM  */
35377887SLiane.Praza@Sun.COM int
scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t * t,scf_values_t * vals)35387887SLiane.Praza@Sun.COM scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t *t, scf_values_t *vals)
35397887SLiane.Praza@Sun.COM {
35407887SLiane.Praza@Sun.COM 	if (_read_astrings_values(t->prt_pg,
35417887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_INTERNAL_SEPARATORS, vals) == NULL) {
35427887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
35437887SLiane.Praza@Sun.COM 			return (-1);
35447887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
35457887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
35467887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
35477887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
35487887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
35497887SLiane.Praza@Sun.COM 
35507887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
35517887SLiane.Praza@Sun.COM 			return (-1);
35527887SLiane.Praza@Sun.COM 
35537887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
35547887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
35557887SLiane.Praza@Sun.COM 		default:
35567887SLiane.Praza@Sun.COM 			assert(0);
35577887SLiane.Praza@Sun.COM 			abort();
35587887SLiane.Praza@Sun.COM 		}
35597887SLiane.Praza@Sun.COM 	} else if (vals->value_count == 0) {
35607887SLiane.Praza@Sun.COM 		/* property has no value */
35617887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
35627887SLiane.Praza@Sun.COM 		scf_values_destroy(vals);
35637887SLiane.Praza@Sun.COM 		return (-1);
35647887SLiane.Praza@Sun.COM 	}
35657887SLiane.Praza@Sun.COM 
35667887SLiane.Praza@Sun.COM 	return (0);
35677887SLiane.Praza@Sun.COM }
35687887SLiane.Praza@Sun.COM 
35697887SLiane.Praza@Sun.COM /*
35707887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
35717887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
35727887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
35737887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
35747887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
35757887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
35767887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
35777887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
35787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
35797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
35807887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
35817887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
35827887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
35837887SLiane.Praza@Sun.COM  */
35847887SLiane.Praza@Sun.COM int
scf_tmpl_value_name_constraints(const scf_prop_tmpl_t * t,scf_values_t * vals)35857887SLiane.Praza@Sun.COM scf_tmpl_value_name_constraints(const scf_prop_tmpl_t *t,
35867887SLiane.Praza@Sun.COM     scf_values_t *vals)
35877887SLiane.Praza@Sun.COM {
35887887SLiane.Praza@Sun.COM 	char **ret;
35897887SLiane.Praza@Sun.COM 
35907887SLiane.Praza@Sun.COM 	ret = _read_astrings_values(t->prt_pg,
35917887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CONSTRAINT_NAME, vals);
35927887SLiane.Praza@Sun.COM 
35937887SLiane.Praza@Sun.COM 	if (ret == NULL) {
35947887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
35957887SLiane.Praza@Sun.COM 			return (-1);
35967887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
35977887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
35987887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
35997887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
36007887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
36017887SLiane.Praza@Sun.COM 
36027887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
36037887SLiane.Praza@Sun.COM 			return (-1);
36047887SLiane.Praza@Sun.COM 
36057887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
36067887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
36077887SLiane.Praza@Sun.COM 		default:
36087887SLiane.Praza@Sun.COM 			assert(0);
36097887SLiane.Praza@Sun.COM 			abort();
36107887SLiane.Praza@Sun.COM 		}
36117887SLiane.Praza@Sun.COM 	} else if (vals->value_count == 0) {
36127887SLiane.Praza@Sun.COM 		/* property has no value */
36137887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
36147887SLiane.Praza@Sun.COM 		scf_values_destroy(vals);
36157887SLiane.Praza@Sun.COM 		return (-1);
36167887SLiane.Praza@Sun.COM 	}
36177887SLiane.Praza@Sun.COM 
36187887SLiane.Praza@Sun.COM 	return (0);
36197887SLiane.Praza@Sun.COM }
36207887SLiane.Praza@Sun.COM 
36217887SLiane.Praza@Sun.COM /*
36227887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
36237887SLiane.Praza@Sun.COM  * Caller is responsible for freeing returned pointer after use.
36247887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
36257887SLiane.Praza@Sun.COM  *    More tokens than the array size supplied.
36267887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
36277887SLiane.Praza@Sun.COM  */
36287887SLiane.Praza@Sun.COM static void *
_separate_by_separator(char * string,const char * sep,char ** array,int size)36297887SLiane.Praza@Sun.COM _separate_by_separator(char *string, const char *sep, char **array, int size)
36307887SLiane.Praza@Sun.COM {
36317887SLiane.Praza@Sun.COM 	char *str, *token;
36327887SLiane.Praza@Sun.COM 	char *lasts;
36337887SLiane.Praza@Sun.COM 	int n = 0;
36347887SLiane.Praza@Sun.COM 
36357887SLiane.Praza@Sun.COM 	assert(array != NULL);
36367887SLiane.Praza@Sun.COM 	assert(string != NULL);
36377887SLiane.Praza@Sun.COM 	assert(sep != NULL);
36387887SLiane.Praza@Sun.COM 	assert(size > 0);
36397887SLiane.Praza@Sun.COM 
36407887SLiane.Praza@Sun.COM 	str = strdup(string);
36417887SLiane.Praza@Sun.COM 	if (str == NULL) {
36427887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
36437887SLiane.Praza@Sun.COM 		return (NULL);
36447887SLiane.Praza@Sun.COM 	}
36457887SLiane.Praza@Sun.COM 
36467887SLiane.Praza@Sun.COM 	if ((array[n] = strtok_r(str, sep, &lasts)) == NULL) {
36477887SLiane.Praza@Sun.COM 		assert(0);
36487887SLiane.Praza@Sun.COM 		abort();
36497887SLiane.Praza@Sun.COM 	}
36507887SLiane.Praza@Sun.COM 
36517887SLiane.Praza@Sun.COM 	n++;
36527887SLiane.Praza@Sun.COM 	while ((token = strtok_r(NULL, sep, &lasts)) != NULL) {
36537887SLiane.Praza@Sun.COM 		if (n >= size) {
36547887SLiane.Praza@Sun.COM 			goto error;
36557887SLiane.Praza@Sun.COM 		}
36567887SLiane.Praza@Sun.COM 		array[n] = token;
36577887SLiane.Praza@Sun.COM 		n++;
36587887SLiane.Praza@Sun.COM 	}
36597887SLiane.Praza@Sun.COM 	if (n < size) {
36607887SLiane.Praza@Sun.COM 		goto error;
36617887SLiane.Praza@Sun.COM 	}
36627887SLiane.Praza@Sun.COM 
36637887SLiane.Praza@Sun.COM 	return (str);
36647887SLiane.Praza@Sun.COM error:
36657887SLiane.Praza@Sun.COM 	free(str);
36667887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
36677887SLiane.Praza@Sun.COM 	return (NULL);
36687887SLiane.Praza@Sun.COM }
36697887SLiane.Praza@Sun.COM 
36707887SLiane.Praza@Sun.COM /*
36717887SLiane.Praza@Sun.COM  * check if name is among values of CHOICES_INCLUDE_VALUES
36727887SLiane.Praza@Sun.COM  * return 0 if name is present, 1 name is not present, -1 on failure
36737887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
36747887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
36757887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
36767887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
36777887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
36787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
36797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
36807887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
36817887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
36827887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
36837887SLiane.Praza@Sun.COM  */
36847887SLiane.Praza@Sun.COM static int
_check_choices_include_values(scf_propertygroup_t * pg,const char * name)36857887SLiane.Praza@Sun.COM _check_choices_include_values(scf_propertygroup_t *pg, const char *name)
36867887SLiane.Praza@Sun.COM {
36877887SLiane.Praza@Sun.COM 	int n = 0, r = 1;
36887887SLiane.Praza@Sun.COM 	char **ret;
36897887SLiane.Praza@Sun.COM 	scf_values_t vals;
36907887SLiane.Praza@Sun.COM 
36917887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(pg,
36927887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES, &vals)) == NULL) {
36937887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
36947887SLiane.Praza@Sun.COM 			return (-1);
36957887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
36967887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
36977887SLiane.Praza@Sun.COM 			return (1);
36987887SLiane.Praza@Sun.COM 
36997887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
37007887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
37017887SLiane.Praza@Sun.COM 			return (-1);
37027887SLiane.Praza@Sun.COM 
37037887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
37047887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
37057887SLiane.Praza@Sun.COM 		default:
37067887SLiane.Praza@Sun.COM 			assert(0);
37077887SLiane.Praza@Sun.COM 			abort();
37087887SLiane.Praza@Sun.COM 		}
37097887SLiane.Praza@Sun.COM 	}
37107887SLiane.Praza@Sun.COM 
37117887SLiane.Praza@Sun.COM 	for (n = 0; n < vals.value_count; ++n) {
37127887SLiane.Praza@Sun.COM 		if (strcmp(name, ret[n]) == 0) {
37137887SLiane.Praza@Sun.COM 			r = 0;
37147887SLiane.Praza@Sun.COM 			break;
37157887SLiane.Praza@Sun.COM 		}
37167887SLiane.Praza@Sun.COM 	}
37177887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
37187887SLiane.Praza@Sun.COM 	return (r);
37197887SLiane.Praza@Sun.COM }
37207887SLiane.Praza@Sun.COM 
37217887SLiane.Praza@Sun.COM void
scf_count_ranges_destroy(scf_count_ranges_t * ranges)37227887SLiane.Praza@Sun.COM scf_count_ranges_destroy(scf_count_ranges_t *ranges)
37237887SLiane.Praza@Sun.COM {
37247887SLiane.Praza@Sun.COM 	if (ranges == NULL)
37257887SLiane.Praza@Sun.COM 		return;
37267887SLiane.Praza@Sun.COM 
37277887SLiane.Praza@Sun.COM 	ranges->scr_num_ranges = 0;
37287887SLiane.Praza@Sun.COM 	free(ranges->scr_min);
37297887SLiane.Praza@Sun.COM 	free(ranges->scr_max);
37307887SLiane.Praza@Sun.COM 	ranges->scr_min = NULL;
37317887SLiane.Praza@Sun.COM 	ranges->scr_max = NULL;
37327887SLiane.Praza@Sun.COM }
37337887SLiane.Praza@Sun.COM 
37347887SLiane.Praza@Sun.COM void
scf_int_ranges_destroy(scf_int_ranges_t * ranges)37357887SLiane.Praza@Sun.COM scf_int_ranges_destroy(scf_int_ranges_t *ranges)
37367887SLiane.Praza@Sun.COM {
37377887SLiane.Praza@Sun.COM 	if (ranges == NULL)
37387887SLiane.Praza@Sun.COM 		return;
37397887SLiane.Praza@Sun.COM 
37407887SLiane.Praza@Sun.COM 	ranges->sir_num_ranges = 0;
37417887SLiane.Praza@Sun.COM 	free(ranges->sir_min);
37427887SLiane.Praza@Sun.COM 	free(ranges->sir_max);
37437887SLiane.Praza@Sun.COM 	ranges->sir_min = NULL;
37447887SLiane.Praza@Sun.COM 	ranges->sir_max = NULL;
37457887SLiane.Praza@Sun.COM }
37467887SLiane.Praza@Sun.COM 
37477887SLiane.Praza@Sun.COM /*
37487887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
37497887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
37507887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
37517887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
37527887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
37537887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
37547887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
37557887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
37567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
37577887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
37587887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
37597887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
37607887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
37617887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
37627887SLiane.Praza@Sun.COM  */
37637887SLiane.Praza@Sun.COM static int
_scf_tmpl_get_count_ranges(const scf_prop_tmpl_t * t,const char * prop,scf_count_ranges_t * ranges)37647887SLiane.Praza@Sun.COM _scf_tmpl_get_count_ranges(const scf_prop_tmpl_t *t, const char *prop,
37657887SLiane.Praza@Sun.COM     scf_count_ranges_t *ranges)
37667887SLiane.Praza@Sun.COM {
37677887SLiane.Praza@Sun.COM 	scf_values_t vals;
37687887SLiane.Praza@Sun.COM 	int i = 0;
37697887SLiane.Praza@Sun.COM 	char **ret;
37707887SLiane.Praza@Sun.COM 	char *one_range[2];
37717887SLiane.Praza@Sun.COM 	char *endptr;
37727887SLiane.Praza@Sun.COM 	char *str = NULL;
37737887SLiane.Praza@Sun.COM 	uint64_t *min = NULL;
37747887SLiane.Praza@Sun.COM 	uint64_t *max = NULL;
37757887SLiane.Praza@Sun.COM 
37767887SLiane.Praza@Sun.COM 	assert(ranges != NULL);
37777887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL)
37787887SLiane.Praza@Sun.COM 		goto error;
37797887SLiane.Praza@Sun.COM 	if (vals.value_count == 0) {
37807887SLiane.Praza@Sun.COM 		/* range values are empty */
37817887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
37827887SLiane.Praza@Sun.COM 		goto cleanup;
37837887SLiane.Praza@Sun.COM 	}
37847887SLiane.Praza@Sun.COM 
37857887SLiane.Praza@Sun.COM 	min = malloc(vals.value_count * sizeof (uint64_t));
37867887SLiane.Praza@Sun.COM 	max = malloc(vals.value_count * sizeof (uint64_t));
37877887SLiane.Praza@Sun.COM 	if (min == NULL || max == NULL) {
37887887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
37897887SLiane.Praza@Sun.COM 		goto cleanup;
37907887SLiane.Praza@Sun.COM 	}
37917887SLiane.Praza@Sun.COM 	for (i = 0; i < vals.value_count; ++i) {
37927887SLiane.Praza@Sun.COM 		/* min and max should be separated by a "," */
37937887SLiane.Praza@Sun.COM 		if ((str = _separate_by_separator(ret[i], ",", one_range,
37947887SLiane.Praza@Sun.COM 		    2)) == NULL)
37957887SLiane.Praza@Sun.COM 			goto cleanup;
37967887SLiane.Praza@Sun.COM 		errno = 0;
37977887SLiane.Praza@Sun.COM 		min[i] = strtoull(one_range[0], &endptr, 10);
37987887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[0] || *endptr) {
37997887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
38007887SLiane.Praza@Sun.COM 			goto cleanup;
38017887SLiane.Praza@Sun.COM 		}
38027887SLiane.Praza@Sun.COM 		errno = 0;
38037887SLiane.Praza@Sun.COM 		max[i] = strtoull(one_range[1], &endptr, 10);
38047887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[1] || *endptr) {
38057887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
38067887SLiane.Praza@Sun.COM 			goto cleanup;
38077887SLiane.Praza@Sun.COM 		}
38087887SLiane.Praza@Sun.COM 		if (min[i] > max[i]) {
38097887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
38107887SLiane.Praza@Sun.COM 			goto cleanup;
38117887SLiane.Praza@Sun.COM 		}
38127887SLiane.Praza@Sun.COM 		free(str);
38137887SLiane.Praza@Sun.COM 		str = NULL;
38147887SLiane.Praza@Sun.COM 	}
38157887SLiane.Praza@Sun.COM 	ranges->scr_num_ranges = vals.value_count;
38167887SLiane.Praza@Sun.COM 	ranges->scr_min = min;
38177887SLiane.Praza@Sun.COM 	ranges->scr_max = max;
38187887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
38197887SLiane.Praza@Sun.COM 	return (0);
38207887SLiane.Praza@Sun.COM cleanup:
38217887SLiane.Praza@Sun.COM 	free(str);
38227887SLiane.Praza@Sun.COM 	free(min);
38237887SLiane.Praza@Sun.COM 	free(max);
38247887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
38257887SLiane.Praza@Sun.COM error:
38267887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
38277887SLiane.Praza@Sun.COM 		return (-1);
38287887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
38297887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
38307887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
38317887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
38327887SLiane.Praza@Sun.COM 
38337887SLiane.Praza@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
38347887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_FOUND:
38357887SLiane.Praza@Sun.COM 		return (-1);
38367887SLiane.Praza@Sun.COM 
38377887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
38387887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
38397887SLiane.Praza@Sun.COM 	default:
38407887SLiane.Praza@Sun.COM 		assert(0);
38417887SLiane.Praza@Sun.COM 		abort();
38427887SLiane.Praza@Sun.COM 	}
38437887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
38447887SLiane.Praza@Sun.COM }
38457887SLiane.Praza@Sun.COM 
38467887SLiane.Praza@Sun.COM /*
38477887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
38487887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
38497887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
38507887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
38517887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
38527887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
38537887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
38547887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
38557887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
38567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
38577887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
38587887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
38597887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
38607887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
38617887SLiane.Praza@Sun.COM  */
38627887SLiane.Praza@Sun.COM static int
_scf_tmpl_get_int_ranges(const scf_prop_tmpl_t * t,const char * prop,scf_int_ranges_t * ranges)38637887SLiane.Praza@Sun.COM _scf_tmpl_get_int_ranges(const scf_prop_tmpl_t *t, const char *prop,
38647887SLiane.Praza@Sun.COM     scf_int_ranges_t *ranges)
38657887SLiane.Praza@Sun.COM {
38667887SLiane.Praza@Sun.COM 	scf_values_t vals;
38677887SLiane.Praza@Sun.COM 	int n = 0;
38687887SLiane.Praza@Sun.COM 	char **ret;
38697887SLiane.Praza@Sun.COM 	char *one_range[2];
38707887SLiane.Praza@Sun.COM 	char *endptr;
38717887SLiane.Praza@Sun.COM 	char *str = NULL;
38727887SLiane.Praza@Sun.COM 	int64_t *min = NULL;
38737887SLiane.Praza@Sun.COM 	int64_t *max = NULL;
38747887SLiane.Praza@Sun.COM 
38757887SLiane.Praza@Sun.COM 	assert(ranges != NULL);
38767887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL)
38777887SLiane.Praza@Sun.COM 		goto error;
38787887SLiane.Praza@Sun.COM 	if (vals.value_count == 0) {
38797887SLiane.Praza@Sun.COM 		/* range values are empty */
38807887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
38817887SLiane.Praza@Sun.COM 		goto cleanup;
38827887SLiane.Praza@Sun.COM 	}
38837887SLiane.Praza@Sun.COM 
38847887SLiane.Praza@Sun.COM 	min = malloc(vals.value_count * sizeof (int64_t));
38857887SLiane.Praza@Sun.COM 	max = malloc(vals.value_count * sizeof (int64_t));
38867887SLiane.Praza@Sun.COM 	if (min == NULL || max == NULL) {
38877887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
38887887SLiane.Praza@Sun.COM 		goto cleanup;
38897887SLiane.Praza@Sun.COM 	}
38907887SLiane.Praza@Sun.COM 	while (n < vals.value_count) {
38917887SLiane.Praza@Sun.COM 		/* min and max should be separated by a "," */
38927887SLiane.Praza@Sun.COM 		if ((str = _separate_by_separator(ret[n], ",", one_range, 2))
38937887SLiane.Praza@Sun.COM 		    == NULL)
38947887SLiane.Praza@Sun.COM 			goto cleanup;
38957887SLiane.Praza@Sun.COM 		errno = 0;
38967887SLiane.Praza@Sun.COM 		min[n] = strtoll(one_range[0], &endptr, 10);
38977887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[0] || *endptr) {
38987887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
38997887SLiane.Praza@Sun.COM 			goto cleanup;
39007887SLiane.Praza@Sun.COM 		}
39017887SLiane.Praza@Sun.COM 		errno = 0;
39027887SLiane.Praza@Sun.COM 		max[n] = strtoll(one_range[1], &endptr, 10);
39037887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[1] || *endptr) {
39047887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
39057887SLiane.Praza@Sun.COM 			goto cleanup;
39067887SLiane.Praza@Sun.COM 		}
39077887SLiane.Praza@Sun.COM 		if (min[n] > max[n]) {
39087887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
39097887SLiane.Praza@Sun.COM 			goto cleanup;
39107887SLiane.Praza@Sun.COM 		}
39117887SLiane.Praza@Sun.COM 		++n;
39127887SLiane.Praza@Sun.COM 		free(str);
39137887SLiane.Praza@Sun.COM 		str = NULL;
39147887SLiane.Praza@Sun.COM 	}
39157887SLiane.Praza@Sun.COM 	ranges->sir_num_ranges = vals.value_count;
39167887SLiane.Praza@Sun.COM 	ranges->sir_min = min;
39177887SLiane.Praza@Sun.COM 	ranges->sir_max = max;
39187887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
39197887SLiane.Praza@Sun.COM 	return (0);
39207887SLiane.Praza@Sun.COM cleanup:
39217887SLiane.Praza@Sun.COM 	free(str);
39227887SLiane.Praza@Sun.COM 	free(min);
39237887SLiane.Praza@Sun.COM 	free(max);
39247887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
39257887SLiane.Praza@Sun.COM error:
39267887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
39277887SLiane.Praza@Sun.COM 		return (-1);
39287887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
39297887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
39307887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
39317887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
39327887SLiane.Praza@Sun.COM 
39337887SLiane.Praza@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
39347887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_FOUND:
39357887SLiane.Praza@Sun.COM 	case SCF_ERROR_TEMPLATE_INVALID:
39367887SLiane.Praza@Sun.COM 		return (-1);
39377887SLiane.Praza@Sun.COM 
39387887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
39397887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
39407887SLiane.Praza@Sun.COM 	default:
39417887SLiane.Praza@Sun.COM 		assert(0);
39427887SLiane.Praza@Sun.COM 		abort();
39437887SLiane.Praza@Sun.COM 	}
39447887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
39457887SLiane.Praza@Sun.COM }
39467887SLiane.Praza@Sun.COM 
39477887SLiane.Praza@Sun.COM /*
39487887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
39497887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
39507887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
39517887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
39527887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
39537887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
39547887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
39557887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
39567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
39577887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
39587887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
39597887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
39607887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
39617887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
39627887SLiane.Praza@Sun.COM  */
39637887SLiane.Praza@Sun.COM int
scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t * t,scf_count_ranges_t * ranges)39647887SLiane.Praza@Sun.COM scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t *t,
39657887SLiane.Praza@Sun.COM     scf_count_ranges_t *ranges)
39667887SLiane.Praza@Sun.COM {
39677887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE,
39687887SLiane.Praza@Sun.COM 	    ranges));
39697887SLiane.Praza@Sun.COM }
39707887SLiane.Praza@Sun.COM 
39717887SLiane.Praza@Sun.COM int
scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t * t,scf_int_ranges_t * ranges)39727887SLiane.Praza@Sun.COM scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t *t,
39737887SLiane.Praza@Sun.COM     scf_int_ranges_t *ranges)
39747887SLiane.Praza@Sun.COM {
39757887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE,
39767887SLiane.Praza@Sun.COM 	    ranges));
39777887SLiane.Praza@Sun.COM }
39787887SLiane.Praza@Sun.COM 
39797887SLiane.Praza@Sun.COM int
scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t * t,scf_count_ranges_t * ranges)39807887SLiane.Praza@Sun.COM scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t *t,
39817887SLiane.Praza@Sun.COM     scf_count_ranges_t *ranges)
39827887SLiane.Praza@Sun.COM {
39837887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE,
39847887SLiane.Praza@Sun.COM 	    ranges));
39857887SLiane.Praza@Sun.COM }
39867887SLiane.Praza@Sun.COM 
39877887SLiane.Praza@Sun.COM int
scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t * t,scf_int_ranges_t * ranges)39887887SLiane.Praza@Sun.COM scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t *t,
39897887SLiane.Praza@Sun.COM     scf_int_ranges_t *ranges)
39907887SLiane.Praza@Sun.COM {
39917887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE,
39927887SLiane.Praza@Sun.COM 	    ranges));
39937887SLiane.Praza@Sun.COM }
39947887SLiane.Praza@Sun.COM 
39957887SLiane.Praza@Sun.COM /*
39967887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
39977887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
39987887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
39997887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
40007887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
40017887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
40027887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
40037887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
40047887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
40057887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
40067887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
40077887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
40087887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
40097887SLiane.Praza@Sun.COM  */
40107887SLiane.Praza@Sun.COM int
scf_tmpl_value_name_choices(const scf_prop_tmpl_t * t,scf_values_t * vals)40117887SLiane.Praza@Sun.COM scf_tmpl_value_name_choices(const scf_prop_tmpl_t *t, scf_values_t *vals)
40127887SLiane.Praza@Sun.COM {
40137887SLiane.Praza@Sun.COM 	int c_flag = 0; /* have not read any value yet */
40147887SLiane.Praza@Sun.COM 	int r;
40157887SLiane.Praza@Sun.COM 	char **ret;
40167887SLiane.Praza@Sun.COM 
40177887SLiane.Praza@Sun.COM 	/* First, look for explicitly declared choices. */
40187887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(t->prt_pg,
40197887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CHOICES_NAME, vals)) != NULL) {
40207887SLiane.Praza@Sun.COM 		c_flag = 1;
40217887SLiane.Praza@Sun.COM 	} else if (scf_error() != SCF_ERROR_NOT_FOUND) {
40227887SLiane.Praza@Sun.COM 		goto error;
40237887SLiane.Praza@Sun.COM 	}
40247887SLiane.Praza@Sun.COM 
40257887SLiane.Praza@Sun.COM 	/* Next, check for choices included by 'values'. */
40267887SLiane.Praza@Sun.COM 	if ((r = _check_choices_include_values(t->prt_pg, "values")) == 0) {
40277887SLiane.Praza@Sun.COM 		/* read values_name */
40287887SLiane.Praza@Sun.COM 		if (c_flag == 1)
40297887SLiane.Praza@Sun.COM 			/* append values */
40307887SLiane.Praza@Sun.COM 			ret = _append_astrings_values(t->prt_pg,
40317887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_VALUES_NAME, vals);
40327887SLiane.Praza@Sun.COM 		else
40337887SLiane.Praza@Sun.COM 			/* read values */
40347887SLiane.Praza@Sun.COM 			ret = _read_astrings_values(t->prt_pg,
40357887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_VALUES_NAME, vals);
40367887SLiane.Praza@Sun.COM 		if (ret != NULL) {
40377887SLiane.Praza@Sun.COM 			c_flag = 1;
40387887SLiane.Praza@Sun.COM 		} else if (scf_error() != SCF_ERROR_NOT_FOUND) {
40397887SLiane.Praza@Sun.COM 			goto error;
40407887SLiane.Praza@Sun.COM 		}
40417887SLiane.Praza@Sun.COM 	} else if (r == -1) {
40427887SLiane.Praza@Sun.COM 		goto error;
40437887SLiane.Praza@Sun.COM 	}
40447887SLiane.Praza@Sun.COM 
40457887SLiane.Praza@Sun.COM 	/* Finally check for choices included by 'constraints'. */
40467887SLiane.Praza@Sun.COM 	if ((r = _check_choices_include_values(t->prt_pg, "constraints")) ==
40477887SLiane.Praza@Sun.COM 	    0) {
40487887SLiane.Praza@Sun.COM 		/* read constraint_name */
40497887SLiane.Praza@Sun.COM 		if (c_flag == 1)
40507887SLiane.Praza@Sun.COM 			/* append values */
40517887SLiane.Praza@Sun.COM 			ret = _append_astrings_values(t->prt_pg,
40527887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_CONSTRAINT_NAME, vals);
40537887SLiane.Praza@Sun.COM 		else
40547887SLiane.Praza@Sun.COM 			/* read values */
40557887SLiane.Praza@Sun.COM 			ret = _read_astrings_values(t->prt_pg,
40567887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_CONSTRAINT_NAME, vals);
40577887SLiane.Praza@Sun.COM 		if (ret != NULL) {
40587887SLiane.Praza@Sun.COM 			c_flag = 1;
40597887SLiane.Praza@Sun.COM 		} else if (scf_error() != SCF_ERROR_NOT_FOUND) {
40607887SLiane.Praza@Sun.COM 			goto error;
40617887SLiane.Praza@Sun.COM 		}
40627887SLiane.Praza@Sun.COM 	} else if (r == -1) {
40637887SLiane.Praza@Sun.COM 		goto error;
40647887SLiane.Praza@Sun.COM 	}
40657887SLiane.Praza@Sun.COM 
40667887SLiane.Praza@Sun.COM 	if (c_flag == 0 || vals->value_count == 0) {
40677887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
40687887SLiane.Praza@Sun.COM 		return (-1);
40697887SLiane.Praza@Sun.COM 	}
40707887SLiane.Praza@Sun.COM 
40717887SLiane.Praza@Sun.COM 	return (0);
40727887SLiane.Praza@Sun.COM 
40737887SLiane.Praza@Sun.COM error:
40747887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
40757887SLiane.Praza@Sun.COM 		return (-1);
40767887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
40777887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
40787887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
40797887SLiane.Praza@Sun.COM 		return (-1);
40807887SLiane.Praza@Sun.COM 
40817887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
40827887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
40837887SLiane.Praza@Sun.COM 	default:
40847887SLiane.Praza@Sun.COM 		assert(0);
40857887SLiane.Praza@Sun.COM 		abort();
40867887SLiane.Praza@Sun.COM 	}
40877887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
40887887SLiane.Praza@Sun.COM }
40897887SLiane.Praza@Sun.COM 
40907887SLiane.Praza@Sun.COM void
scf_values_destroy(scf_values_t * vals)40917887SLiane.Praza@Sun.COM scf_values_destroy(scf_values_t *vals)
40927887SLiane.Praza@Sun.COM {
40937887SLiane.Praza@Sun.COM 	int i;
40947887SLiane.Praza@Sun.COM 	char **items = NULL;
4095*12967Sgavin.maltby@oracle.com 	char **str = NULL;
40967887SLiane.Praza@Sun.COM 
40977887SLiane.Praza@Sun.COM 	if (vals == NULL)
40987887SLiane.Praza@Sun.COM 		return;
40997887SLiane.Praza@Sun.COM 
4100*12967Sgavin.maltby@oracle.com 	str = vals->values_as_strings;
4101*12967Sgavin.maltby@oracle.com 
41027887SLiane.Praza@Sun.COM 	/* free values */
41037887SLiane.Praza@Sun.COM 	switch (vals->value_type) {
41047887SLiane.Praza@Sun.COM 	case SCF_TYPE_BOOLEAN:
41057887SLiane.Praza@Sun.COM 		free(vals->values.v_boolean);
41067887SLiane.Praza@Sun.COM 		break;
41077887SLiane.Praza@Sun.COM 	case SCF_TYPE_COUNT:
41087887SLiane.Praza@Sun.COM 		free(vals->values.v_count);
41097887SLiane.Praza@Sun.COM 		break;
41107887SLiane.Praza@Sun.COM 	case SCF_TYPE_INTEGER:
41117887SLiane.Praza@Sun.COM 		free(vals->values.v_integer);
41127887SLiane.Praza@Sun.COM 		break;
41137887SLiane.Praza@Sun.COM 	case SCF_TYPE_ASTRING:
41147887SLiane.Praza@Sun.COM 		items = vals->values.v_astring;
41157887SLiane.Praza@Sun.COM 		str = NULL;
41167887SLiane.Praza@Sun.COM 		break;
41177887SLiane.Praza@Sun.COM 	case SCF_TYPE_USTRING:
41187887SLiane.Praza@Sun.COM 		items = vals->values.v_ustring;
41197887SLiane.Praza@Sun.COM 		str = NULL;
41207887SLiane.Praza@Sun.COM 		break;
41217887SLiane.Praza@Sun.COM 	case SCF_TYPE_OPAQUE:
41227887SLiane.Praza@Sun.COM 		items = vals->values.v_opaque;
41237887SLiane.Praza@Sun.COM 		str = NULL;
41247887SLiane.Praza@Sun.COM 		break;
41257887SLiane.Praza@Sun.COM 	case SCF_TYPE_TIME:
41267887SLiane.Praza@Sun.COM 		free(vals->values.v_time);
41277887SLiane.Praza@Sun.COM 		break;
41287887SLiane.Praza@Sun.COM 	default:
41297887SLiane.Praza@Sun.COM 		assert(0);
41307887SLiane.Praza@Sun.COM 		abort();
41317887SLiane.Praza@Sun.COM 	}
41327887SLiane.Praza@Sun.COM 	for (i = 0; i < vals->value_count; ++i) {
41337887SLiane.Praza@Sun.COM 		if (items != NULL)
41347887SLiane.Praza@Sun.COM 			free(items[i]);
41357887SLiane.Praza@Sun.COM 		if (str != NULL)
41367887SLiane.Praza@Sun.COM 			free(str[i]);
41377887SLiane.Praza@Sun.COM 	}
41387887SLiane.Praza@Sun.COM 	vals->value_count = 0;
41397887SLiane.Praza@Sun.COM 	free(items);
41407887SLiane.Praza@Sun.COM 	free(str);
41417887SLiane.Praza@Sun.COM }
41427887SLiane.Praza@Sun.COM 
41437887SLiane.Praza@Sun.COM /*
41447887SLiane.Praza@Sun.COM  * char *_make_value_name()
41457887SLiane.Praza@Sun.COM  *
41467887SLiane.Praza@Sun.COM  * Construct the prefix for a value common name or value description property.
41477887SLiane.Praza@Sun.COM  * It takes the form:
41487887SLiane.Praza@Sun.COM  *   value_<BASE32 name>_<common_name|description>_
41497887SLiane.Praza@Sun.COM  * This is then combined with a localized suffix by the caller to look
41507887SLiane.Praza@Sun.COM  * up the property in the repository:
41517887SLiane.Praza@Sun.COM  *   value_<BASE32 name>_<common_name|description>_<lang>
41527887SLiane.Praza@Sun.COM  *
41537887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
41547887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
41557887SLiane.Praza@Sun.COM  *     Name isn't short enough make a value name with.
41567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
41577887SLiane.Praza@Sun.COM  */
41587887SLiane.Praza@Sun.COM static char *
_make_value_name(char * desc_name,const char * value)41597887SLiane.Praza@Sun.COM _make_value_name(char *desc_name, const char *value)
41607887SLiane.Praza@Sun.COM {
41617887SLiane.Praza@Sun.COM 	char *name = NULL;
41627887SLiane.Praza@Sun.COM 	char *encoded = NULL;
41637887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
41647887SLiane.Praza@Sun.COM 
41657887SLiane.Praza@Sun.COM 	name = malloc(sz);
41667887SLiane.Praza@Sun.COM 	encoded = malloc(sz);
41677887SLiane.Praza@Sun.COM 	if (name == NULL || encoded == NULL) {
41687887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
41697887SLiane.Praza@Sun.COM 		free(name);
41707887SLiane.Praza@Sun.COM 		free(encoded);
41717887SLiane.Praza@Sun.COM 		return (NULL);
41727887SLiane.Praza@Sun.COM 	}
41737887SLiane.Praza@Sun.COM 
41747887SLiane.Praza@Sun.COM 	if (scf_encode32(value, strlen(value), encoded, sz, NULL,
41757887SLiane.Praza@Sun.COM 	    SCF_ENCODE32_PAD) != 0) {
41767887SLiane.Praza@Sun.COM 		/* Shouldn't happen. */
41777887SLiane.Praza@Sun.COM 		assert(0);
41787887SLiane.Praza@Sun.COM 	}
41797887SLiane.Praza@Sun.COM 
41807887SLiane.Praza@Sun.COM 	(void) strlcpy(name, SCF_PROPERTY_TM_VALUE_PREFIX, sz);
41817887SLiane.Praza@Sun.COM 
41827887SLiane.Praza@Sun.COM 	if (strlcat(name, encoded, sz) >= sz) {
41837887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
41847887SLiane.Praza@Sun.COM 		free(name);
41857887SLiane.Praza@Sun.COM 		free(encoded);
41867887SLiane.Praza@Sun.COM 		return (NULL);
41877887SLiane.Praza@Sun.COM 	}
41887887SLiane.Praza@Sun.COM 
41897887SLiane.Praza@Sun.COM 	if (strlcat(name, "_", sz) >= sz) {
41907887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
41917887SLiane.Praza@Sun.COM 		free(name);
41927887SLiane.Praza@Sun.COM 		free(encoded);
41937887SLiane.Praza@Sun.COM 		return (NULL);
41947887SLiane.Praza@Sun.COM 	}
41957887SLiane.Praza@Sun.COM 
41967887SLiane.Praza@Sun.COM 	if (strlcat(name, desc_name, sz) >= sz) {
41977887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
41987887SLiane.Praza@Sun.COM 		free(name);
41997887SLiane.Praza@Sun.COM 		free(encoded);
42007887SLiane.Praza@Sun.COM 		return (NULL);
42017887SLiane.Praza@Sun.COM 	}
42027887SLiane.Praza@Sun.COM 
42037887SLiane.Praza@Sun.COM 	if (strlcat(name, "_", sz) >= sz) {
42047887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
42057887SLiane.Praza@Sun.COM 		free(name);
42067887SLiane.Praza@Sun.COM 		free(encoded);
42077887SLiane.Praza@Sun.COM 		return (NULL);
42087887SLiane.Praza@Sun.COM 	}
42097887SLiane.Praza@Sun.COM 
42107887SLiane.Praza@Sun.COM 	free(encoded);
42117887SLiane.Praza@Sun.COM 	return (name);
42127887SLiane.Praza@Sun.COM }
42137887SLiane.Praza@Sun.COM 
42147887SLiane.Praza@Sun.COM /*
42157887SLiane.Praza@Sun.COM  * ssize_t scf_tmpl_value_common_name()
42167887SLiane.Praza@Sun.COM  *
42177887SLiane.Praza@Sun.COM  * Populates "out" with an allocated string containing the value's
42187887SLiane.Praza@Sun.COM  * common name.  Returns the size of the string on successful return.
42197887SLiane.Praza@Sun.COM  * out must be freed with free() on successful return.
42207887SLiane.Praza@Sun.COM  *
42217887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
42227887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
42237887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
42247887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
42257887SLiane.Praza@Sun.COM  *     Property group was deleted.
42267887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
42277887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
42287887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
42297887SLiane.Praza@Sun.COM  *     name not a valid property name
42307887SLiane.Praza@Sun.COM  *     name and locale are too long to make a property name
42317887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
42327887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
42337887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
42347887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
42357887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
42367887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
42377887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
42387887SLiane.Praza@Sun.COM  *     property is not SCF_TYPE_ASTRING has more than one value.
42397887SLiane.Praza@Sun.COM  */
42407887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_value_common_name(const scf_prop_tmpl_t * t,const char * locale,const char * value,char ** out)42417887SLiane.Praza@Sun.COM scf_tmpl_value_common_name(const scf_prop_tmpl_t *t, const char *locale,
42427887SLiane.Praza@Sun.COM     const char *value, char **out)
42437887SLiane.Praza@Sun.COM {
42447887SLiane.Praza@Sun.COM 	char *value_name = NULL;
42457887SLiane.Praza@Sun.COM 
42467887SLiane.Praza@Sun.COM 	value_name = _make_value_name("common_name", value);
42477887SLiane.Praza@Sun.COM 	if (value_name == NULL)
42487887SLiane.Praza@Sun.COM 		return (-1);
42497887SLiane.Praza@Sun.COM 
42507887SLiane.Praza@Sun.COM 	*out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale);
42517887SLiane.Praza@Sun.COM 
42527887SLiane.Praza@Sun.COM 	free(value_name);
42537887SLiane.Praza@Sun.COM 
42547887SLiane.Praza@Sun.COM 	if (*out == NULL)
42557887SLiane.Praza@Sun.COM 		return (-1);
42567887SLiane.Praza@Sun.COM 
42577887SLiane.Praza@Sun.COM 	return (strlen(*out));
42587887SLiane.Praza@Sun.COM }
42597887SLiane.Praza@Sun.COM 
42607887SLiane.Praza@Sun.COM /*
42617887SLiane.Praza@Sun.COM  * ssize_t scf_tmpl_value_description()
42627887SLiane.Praza@Sun.COM  *
42637887SLiane.Praza@Sun.COM  * Populates "out" with an allocated string containing the value's
42647887SLiane.Praza@Sun.COM  * description.  Returns the size of the string on successful return.
42657887SLiane.Praza@Sun.COM  * out must be freed with free() on successful return.
42667887SLiane.Praza@Sun.COM  *
42677887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
42687887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
42697887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
42707887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
42717887SLiane.Praza@Sun.COM  *     Property group was deleted.
42727887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
42737887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
42747887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
42757887SLiane.Praza@Sun.COM  *     name not a valid property name
42767887SLiane.Praza@Sun.COM  *     name and locale are too long to make a property name
42777887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
42787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
42797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
42807887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
42817887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
42827887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
42837887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
42847887SLiane.Praza@Sun.COM  *     property is not SCF_TYPE_ASTRING has more than one value.
42857887SLiane.Praza@Sun.COM  */
42867887SLiane.Praza@Sun.COM ssize_t
scf_tmpl_value_description(const scf_prop_tmpl_t * t,const char * locale,const char * value,char ** out)42877887SLiane.Praza@Sun.COM scf_tmpl_value_description(const scf_prop_tmpl_t *t, const char *locale,
42887887SLiane.Praza@Sun.COM     const char *value, char **out)
42897887SLiane.Praza@Sun.COM {
42907887SLiane.Praza@Sun.COM 	char *value_name = NULL;
42917887SLiane.Praza@Sun.COM 
42927887SLiane.Praza@Sun.COM 	value_name = _make_value_name("description", value);
42937887SLiane.Praza@Sun.COM 	if (value_name == NULL)
42947887SLiane.Praza@Sun.COM 		return (-1);
42957887SLiane.Praza@Sun.COM 
42967887SLiane.Praza@Sun.COM 
42977887SLiane.Praza@Sun.COM 	*out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale);
42987887SLiane.Praza@Sun.COM 
42997887SLiane.Praza@Sun.COM 	free(value_name);
43007887SLiane.Praza@Sun.COM 
43017887SLiane.Praza@Sun.COM 	if (*out == NULL)
43027887SLiane.Praza@Sun.COM 		return (-1);
43037887SLiane.Praza@Sun.COM 
43047887SLiane.Praza@Sun.COM 	return (strlen(*out));
43057887SLiane.Praza@Sun.COM }
43067887SLiane.Praza@Sun.COM 
43077887SLiane.Praza@Sun.COM /*
43087887SLiane.Praza@Sun.COM  * Templates error messages format, in human readable form.
43097887SLiane.Praza@Sun.COM  * Each line is one error item:
43107887SLiane.Praza@Sun.COM  *
43117887SLiane.Praza@Sun.COM  * prefix error message
43127887SLiane.Praza@Sun.COM  * 	FMRI="err->te_errs->tes_fmri"
43137887SLiane.Praza@Sun.COM  * 	Property group="err->te_pg_name"
43147887SLiane.Praza@Sun.COM  * 	Property name="err->te_prop_name"
43157887SLiane.Praza@Sun.COM  * 	expected value 1="err->te_ev1"
43167887SLiane.Praza@Sun.COM  * 	expected value 2="err->te_ev2"
43177887SLiane.Praza@Sun.COM  * 	actual value="err->te_actual"
43187887SLiane.Praza@Sun.COM  * 	Tempalte source="err->te_tmpl_fmri"
43197887SLiane.Praza@Sun.COM  * 	pg_pattern name="err->tmpl_pg_name"
43207887SLiane.Praza@Sun.COM  * 	pg_pattern type="err->tmpl_pg_type"
43217887SLiane.Praza@Sun.COM  * 	prop_pattern name="err->tmpl_prop_name"
43227887SLiane.Praza@Sun.COM  * 	prop_pattern type="err->tmpl_prop_type"
43237887SLiane.Praza@Sun.COM  *
43247887SLiane.Praza@Sun.COM  * To add a new error type, include scf_tmpl_error_type_t in libscf.h
43257887SLiane.Praza@Sun.COM  * add one entry in em_desc[], and update the functions pointed by the
43267887SLiane.Praza@Sun.COM  * _tmpl_error_access array with the new error code. Also, update the
43277887SLiane.Praza@Sun.COM  * scf_tmpl_error_* functions to provide access to desired
43287887SLiane.Praza@Sun.COM  * scf_tmpl_error_t fields.
43297887SLiane.Praza@Sun.COM  *
43307887SLiane.Praza@Sun.COM  * To add a new error item, add a new field to scf_tmpl_error_t, a new field
43317887SLiane.Praza@Sun.COM  * in _scf_tmpl_error_desc or a new non-error-dependent string, add a new entry
43327887SLiane.Praza@Sun.COM  * in _tmpl_error_access array and create the appropriate get_val, get_desc
43337887SLiane.Praza@Sun.COM  * functions.
43347887SLiane.Praza@Sun.COM  *
43357887SLiane.Praza@Sun.COM  * Changes to both the validation logic and the error types and items must
43367887SLiane.Praza@Sun.COM  * be coordinated with the code in svccfg to ensure both libscf and svccfg's
43377887SLiane.Praza@Sun.COM  * manifest validation validate the same things.
43387887SLiane.Praza@Sun.COM  */
43397887SLiane.Praza@Sun.COM 
43407887SLiane.Praza@Sun.COM /*
43417887SLiane.Praza@Sun.COM  * Container for all template errors on a validated object.
43427887SLiane.Praza@Sun.COM  */
43437887SLiane.Praza@Sun.COM struct scf_tmpl_errors {
43447887SLiane.Praza@Sun.COM 	int			tes_index;
43457887SLiane.Praza@Sun.COM 	int			tes_num_errs;
43467887SLiane.Praza@Sun.COM 	scf_tmpl_error_t	**tes_errs;
43477887SLiane.Praza@Sun.COM 	int			tes_errs_size;
43487887SLiane.Praza@Sun.COM 	const char		*tes_fmri;
43497887SLiane.Praza@Sun.COM 	const char		*tes_prefix;
43507887SLiane.Praza@Sun.COM 	int			tes_flag; /* if set, scf_tmpl_error_destroy */
43517887SLiane.Praza@Sun.COM 					    /* will free strings in tes_errs  */
43527887SLiane.Praza@Sun.COM };
43537887SLiane.Praza@Sun.COM 
43547887SLiane.Praza@Sun.COM /*
43557887SLiane.Praza@Sun.COM  * Templates error-dependent labels
43567887SLiane.Praza@Sun.COM  */
43577887SLiane.Praza@Sun.COM struct _scf_tmpl_error_desc {
43587887SLiane.Praza@Sun.COM 	const char *em_msg;
43597887SLiane.Praza@Sun.COM 	const char *em_ev1;
43607887SLiane.Praza@Sun.COM 	const char *em_ev2;
43617887SLiane.Praza@Sun.COM 	const char *em_actual;
43627887SLiane.Praza@Sun.COM };
43637887SLiane.Praza@Sun.COM 
43647887SLiane.Praza@Sun.COM /*
43657887SLiane.Praza@Sun.COM  * This array MUST be kept in synch with the template error definition of
43667887SLiane.Praza@Sun.COM  * scf_tmpl_error_type_t in libscf.h
43677887SLiane.Praza@Sun.COM  */
43687887SLiane.Praza@Sun.COM static struct _scf_tmpl_error_desc em_desc[] = {
43697887SLiane.Praza@Sun.COM 	/* SCF_TERR_MISSING_PG */
43707887SLiane.Praza@Sun.COM 	{ "Required property group missing", "Name of missing property group",
43717887SLiane.Praza@Sun.COM 	    "Type of missing property group", NULL },
43727887SLiane.Praza@Sun.COM 	/* SCF_TERR_WRONG_PG_TYPE */
43737887SLiane.Praza@Sun.COM 	{ "Property group has bad type", "Specified type", NULL,
43747887SLiane.Praza@Sun.COM 	    "Actual type" },
43757887SLiane.Praza@Sun.COM 	/* SCF_TERR_MISSING_PROP */
43767887SLiane.Praza@Sun.COM 	{ "Required property missing", "Name of missing property", NULL, NULL },
43777887SLiane.Praza@Sun.COM 	/* SCF_TERR_WRONG_PROP_TYPE */
43787887SLiane.Praza@Sun.COM 	{ "Property has bad type", "Specified property type", NULL,
43797887SLiane.Praza@Sun.COM 	    "Actual property type" },
43807887SLiane.Praza@Sun.COM 	/* SCF_TERR_CARDINALITY_VIOLATION */
43817887SLiane.Praza@Sun.COM 	{ "Number of property values violates cardinality restriction",
43827887SLiane.Praza@Sun.COM 	    "Cardinality minimum", "Cardinality maximum",
43837887SLiane.Praza@Sun.COM 	    "Actual number of values" },
43847887SLiane.Praza@Sun.COM 	/* SCF_TERR_VALUE_CONSTRAINT_VIOLATED */
43857887SLiane.Praza@Sun.COM 	{ "Property has illegal value", NULL, NULL, "Illegal value" },
43867887SLiane.Praza@Sun.COM 	/* SCF_TERR_RANGE_VIOLATION */
43877887SLiane.Praza@Sun.COM 	{ "Property value is out of range", NULL, NULL, "Actual value" },
43887887SLiane.Praza@Sun.COM 	/* SCF_TERR_PG_REDEFINE */
43897887SLiane.Praza@Sun.COM 	{ "Instance redefines pg_pattern", "Instance pg_pattern name",
43907887SLiane.Praza@Sun.COM 	    "Instance pg_pattern type", NULL },
43917887SLiane.Praza@Sun.COM 	/* SCF_TERR_PROP_TYPE_MISMATCH */
43927887SLiane.Praza@Sun.COM 	{ "Property type and value type mismatch", NULL, NULL, "Value type" },
43937887SLiane.Praza@Sun.COM 	/* SCF_TERR_VALUE_OUT_OF_RANGE */
43947887SLiane.Praza@Sun.COM 	{ "Value is out of range", NULL, NULL, "Value" },
43957887SLiane.Praza@Sun.COM 	/* SCF_TERR_INVALID_VALUE */
43967887SLiane.Praza@Sun.COM 	{ "Value is not valid", NULL, NULL, "Value" },
43977887SLiane.Praza@Sun.COM 	/* SCF_TERR_PG_PATTERN_CONFLICT */
43987887SLiane.Praza@Sun.COM 	{ "Conflicting pg_pattern specifications", "Template source",
43997887SLiane.Praza@Sun.COM 	    "pg_pattern name", "pg_pattern type" },
44007887SLiane.Praza@Sun.COM 	/* SCF_TERR_PROP_PATTERN_CONFLICT */
44017887SLiane.Praza@Sun.COM 	{ "Conflicting prop_pattern specifications", "Template source",
44027887SLiane.Praza@Sun.COM 	    "prop_pattern name", "prop_pattern type" },
44037887SLiane.Praza@Sun.COM 	/* SCF_TERR_GENERAL_REDEFINE */
44047887SLiane.Praza@Sun.COM 	{ "Service or instance pg_pattern redefines a global or restarter "
44057887SLiane.Praza@Sun.COM 	    "pg_pattern", "Template source", "pg_pattern name",
44067887SLiane.Praza@Sun.COM 	    "pg_pattern type" },
44077887SLiane.Praza@Sun.COM 	/* SCF_TERR_INCLUDE_VALUES */
44087887SLiane.Praza@Sun.COM 	{ "Missing constraints or values for include_values element",
44097887SLiane.Praza@Sun.COM 	    "include_values type", NULL, NULL },
44107887SLiane.Praza@Sun.COM 	/* SCF_TERR_PG_PATTERN_INCOMPLETE */
44117887SLiane.Praza@Sun.COM 	{ "Required pg_pattern is missing a name or type attribute",
44127887SLiane.Praza@Sun.COM 	    NULL, NULL, NULL },
44137887SLiane.Praza@Sun.COM 	/* SCF_TERR_PROP_PATTERN_INCOMPLETE */
44147887SLiane.Praza@Sun.COM 	{ "Required prop_pattern is missing a type attribute",
44157887SLiane.Praza@Sun.COM 	    NULL, NULL, NULL }
44167887SLiane.Praza@Sun.COM };
44177887SLiane.Praza@Sun.COM 
44187887SLiane.Praza@Sun.COM /*
44197887SLiane.Praza@Sun.COM  * Templates non error-dependent labels
44207887SLiane.Praza@Sun.COM  */
44217887SLiane.Praza@Sun.COM static const char *em_fmri = "FMRI";
44227887SLiane.Praza@Sun.COM static const char *em_pg_name = "Property group";
44237887SLiane.Praza@Sun.COM static const char *em_prop_name = "Property name";
44247887SLiane.Praza@Sun.COM static const char *em_tmpl_fmri = "Template source";
44257887SLiane.Praza@Sun.COM static const char *em_tmpl_pg_name = "pg_pattern name";
44267887SLiane.Praza@Sun.COM static const char *em_tmpl_pg_type = "pg_pattern type";
44277887SLiane.Praza@Sun.COM static const char *em_tmpl_prop_name = "prop_pattern name";
44287887SLiane.Praza@Sun.COM static const char *em_tmpl_prop_type = "prop_pattern type";
44297887SLiane.Praza@Sun.COM 
44307887SLiane.Praza@Sun.COM static const char *
_get_fmri_desc(scf_tmpl_error_t * err)44317887SLiane.Praza@Sun.COM _get_fmri_desc(scf_tmpl_error_t *err)
44327887SLiane.Praza@Sun.COM {
44337887SLiane.Praza@Sun.COM 	switch (err->te_type) {
44347887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
44357887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
44367887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
44377887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
44387887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
44397887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
44407887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
44417887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
44427887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
44437887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
44447887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
44457887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_fmri));
44467887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
44477887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
44487887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
44497887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
44507887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
44517887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
44527887SLiane.Praza@Sun.COM 	default:
44537887SLiane.Praza@Sun.COM 		return (NULL);
44547887SLiane.Praza@Sun.COM 	}
44557887SLiane.Praza@Sun.COM }
44567887SLiane.Praza@Sun.COM 
44577887SLiane.Praza@Sun.COM static const char *
_get_pg_name_desc(scf_tmpl_error_t * err)44587887SLiane.Praza@Sun.COM _get_pg_name_desc(scf_tmpl_error_t *err)
44597887SLiane.Praza@Sun.COM {
44607887SLiane.Praza@Sun.COM 	switch (err->te_type) {
44617887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
44627887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
44637887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
44647887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
44657887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
44667887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
44677887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_pg_name));
44687887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
44697887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
44707887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
44717887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
44727887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
44737887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
44747887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
44757887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
44767887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
44777887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
44787887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
44797887SLiane.Praza@Sun.COM 	default:
44807887SLiane.Praza@Sun.COM 		return (NULL);
44817887SLiane.Praza@Sun.COM 	}
44827887SLiane.Praza@Sun.COM }
44837887SLiane.Praza@Sun.COM 
44847887SLiane.Praza@Sun.COM static const char *
_get_prop_name_desc(scf_tmpl_error_t * err)44857887SLiane.Praza@Sun.COM _get_prop_name_desc(scf_tmpl_error_t *err)
44867887SLiane.Praza@Sun.COM {
44877887SLiane.Praza@Sun.COM 	switch (err->te_type) {
44887887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
44897887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
44907887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
44917887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
44927887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_prop_name));
44937887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
44947887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
44957887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
44967887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
44977887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
44987887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
44997887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
45007887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
45017887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
45027887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
45037887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
45047887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
45057887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
45067887SLiane.Praza@Sun.COM 	default:
45077887SLiane.Praza@Sun.COM 		return (NULL);
45087887SLiane.Praza@Sun.COM 	}
45097887SLiane.Praza@Sun.COM }
45107887SLiane.Praza@Sun.COM 
45117887SLiane.Praza@Sun.COM static const char *
_get_ev1_desc(scf_tmpl_error_t * err)45127887SLiane.Praza@Sun.COM _get_ev1_desc(scf_tmpl_error_t *err)
45137887SLiane.Praza@Sun.COM {
45147887SLiane.Praza@Sun.COM 	switch (err->te_type) {
45157887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
45167887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
45177887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
45187887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
45197887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
45207887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
45217887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
45227887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
45237887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
45247887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
45257887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
45267887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev1));
45277887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
45287887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
45297887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
45307887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
45317887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
45327887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
45337887SLiane.Praza@Sun.COM 	default:
45347887SLiane.Praza@Sun.COM 		return (NULL);
45357887SLiane.Praza@Sun.COM 	}
45367887SLiane.Praza@Sun.COM }
45377887SLiane.Praza@Sun.COM 
45387887SLiane.Praza@Sun.COM static const char *
_get_ev2_desc(scf_tmpl_error_t * err)45397887SLiane.Praza@Sun.COM _get_ev2_desc(scf_tmpl_error_t *err)
45407887SLiane.Praza@Sun.COM {
45417887SLiane.Praza@Sun.COM 	switch (err->te_type) {
45427887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
45437887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
45447887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
45457887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
45467887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
45477887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
45487887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
45497887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev2));
45507887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
45517887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
45527887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
45537887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
45547887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
45557887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
45567887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
45577887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
45587887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
45597887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
45607887SLiane.Praza@Sun.COM 	default:
45617887SLiane.Praza@Sun.COM 		return (NULL);
45627887SLiane.Praza@Sun.COM 	}
45637887SLiane.Praza@Sun.COM }
45647887SLiane.Praza@Sun.COM 
45657887SLiane.Praza@Sun.COM static const char *
_get_actual_desc(scf_tmpl_error_t * err)45667887SLiane.Praza@Sun.COM _get_actual_desc(scf_tmpl_error_t *err)
45677887SLiane.Praza@Sun.COM {
45687887SLiane.Praza@Sun.COM 	switch (err->te_type) {
45697887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
45707887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
45717887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
45727887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
45737887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
45747887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
45757887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
45767887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
45777887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
45787887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
45797887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
45807887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
45817887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
45827887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN,
45837887SLiane.Praza@Sun.COM 		    em_desc[err->te_type].em_actual));
45847887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
45857887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
45867887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
45877887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
45887887SLiane.Praza@Sun.COM 	default:
45897887SLiane.Praza@Sun.COM 		return (NULL);
45907887SLiane.Praza@Sun.COM 	}
45917887SLiane.Praza@Sun.COM }
45927887SLiane.Praza@Sun.COM 
45937887SLiane.Praza@Sun.COM static const char *
_get_tmpl_fmri_desc(scf_tmpl_error_t * err)45947887SLiane.Praza@Sun.COM _get_tmpl_fmri_desc(scf_tmpl_error_t *err)
45957887SLiane.Praza@Sun.COM {
45967887SLiane.Praza@Sun.COM 	switch (err->te_type) {
45977887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
45987887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
45997887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
46007887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
46017887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
46027887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
46037887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
46047887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
46057887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
46067887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
46077887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
46087887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
46097887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
46107887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
46117887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
46127887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
46137887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
46147887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_fmri));
46157887SLiane.Praza@Sun.COM 	default:
46167887SLiane.Praza@Sun.COM 		return (NULL);
46177887SLiane.Praza@Sun.COM 	}
46187887SLiane.Praza@Sun.COM }
46197887SLiane.Praza@Sun.COM 
46207887SLiane.Praza@Sun.COM static const char *
_get_tmpl_pg_name_desc(scf_tmpl_error_t * err)46217887SLiane.Praza@Sun.COM _get_tmpl_pg_name_desc(scf_tmpl_error_t *err)
46227887SLiane.Praza@Sun.COM {
46237887SLiane.Praza@Sun.COM 	switch (err->te_type) {
46247887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
46257887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
46267887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
46277887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
46287887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
46297887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
46307887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
46317887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
46327887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
46337887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
46347887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
46357887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
46367887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
46377887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
46387887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
46397887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
46407887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
46417887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_pg_name));
46427887SLiane.Praza@Sun.COM 	default:
46437887SLiane.Praza@Sun.COM 		return (NULL);
46447887SLiane.Praza@Sun.COM 	}
46457887SLiane.Praza@Sun.COM }
46467887SLiane.Praza@Sun.COM 
46477887SLiane.Praza@Sun.COM static const char *
_get_tmpl_pg_type_desc(scf_tmpl_error_t * err)46487887SLiane.Praza@Sun.COM _get_tmpl_pg_type_desc(scf_tmpl_error_t *err)
46497887SLiane.Praza@Sun.COM {
46507887SLiane.Praza@Sun.COM 	switch (err->te_type) {
46517887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
46527887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
46537887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
46547887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
46557887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
46567887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
46577887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
46587887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
46597887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
46607887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
46617887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
46627887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
46637887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
46647887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
46657887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
46667887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
46677887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
46687887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_pg_type));
46697887SLiane.Praza@Sun.COM 	default:
46707887SLiane.Praza@Sun.COM 		return (NULL);
46717887SLiane.Praza@Sun.COM 	}
46727887SLiane.Praza@Sun.COM }
46737887SLiane.Praza@Sun.COM 
46747887SLiane.Praza@Sun.COM static const char *
_get_tmpl_prop_name_desc(scf_tmpl_error_t * err)46757887SLiane.Praza@Sun.COM _get_tmpl_prop_name_desc(scf_tmpl_error_t *err)
46767887SLiane.Praza@Sun.COM {
46777887SLiane.Praza@Sun.COM 	switch (err->te_type) {
46787887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
46797887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
46807887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
46817887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
46827887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
46837887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
46847887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
46857887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
46867887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
46877887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
46887887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
46897887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_prop_name));
46907887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
46917887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
46927887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
46937887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
46947887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
46957887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
46967887SLiane.Praza@Sun.COM 	default:
46977887SLiane.Praza@Sun.COM 		return (NULL);
46987887SLiane.Praza@Sun.COM 	}
46997887SLiane.Praza@Sun.COM }
47007887SLiane.Praza@Sun.COM 
47017887SLiane.Praza@Sun.COM static const char *
_get_tmpl_prop_type_desc(scf_tmpl_error_t * err)47027887SLiane.Praza@Sun.COM _get_tmpl_prop_type_desc(scf_tmpl_error_t *err)
47037887SLiane.Praza@Sun.COM {
47047887SLiane.Praza@Sun.COM 	switch (err->te_type) {
47057887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
47067887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
47077887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
47087887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
47097887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
47107887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
47117887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
47127887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
47137887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
47147887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
47157887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_prop_type));
47167887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
47177887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
47187887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
47197887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
47207887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
47217887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
47227887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
47237887SLiane.Praza@Sun.COM 	default:
47247887SLiane.Praza@Sun.COM 		return (NULL);
47257887SLiane.Praza@Sun.COM 	}
47267887SLiane.Praza@Sun.COM }
47277887SLiane.Praza@Sun.COM 
47287887SLiane.Praza@Sun.COM static const char *
_get_fmri_val(scf_tmpl_error_t * err)47297887SLiane.Praza@Sun.COM _get_fmri_val(scf_tmpl_error_t *err)
47307887SLiane.Praza@Sun.COM {
47317887SLiane.Praza@Sun.COM 	assert(err != NULL && err->te_errs != NULL &&
47327887SLiane.Praza@Sun.COM 	    err->te_errs->tes_fmri != NULL);
47337887SLiane.Praza@Sun.COM 	return (err->te_errs->tes_fmri);
47347887SLiane.Praza@Sun.COM }
47357887SLiane.Praza@Sun.COM 
47367887SLiane.Praza@Sun.COM static const char *
_get_pg_name_val(scf_tmpl_error_t * err)47377887SLiane.Praza@Sun.COM _get_pg_name_val(scf_tmpl_error_t *err)
47387887SLiane.Praza@Sun.COM {
47397887SLiane.Praza@Sun.COM 	assert(err != NULL);
47407887SLiane.Praza@Sun.COM 	return (err->te_pg_name);
47417887SLiane.Praza@Sun.COM }
47427887SLiane.Praza@Sun.COM 
47437887SLiane.Praza@Sun.COM static const char *
_get_prop_name_val(scf_tmpl_error_t * err)47447887SLiane.Praza@Sun.COM _get_prop_name_val(scf_tmpl_error_t *err)
47457887SLiane.Praza@Sun.COM {
47467887SLiane.Praza@Sun.COM 	assert(err != NULL);
47477887SLiane.Praza@Sun.COM 	return (err->te_prop_name);
47487887SLiane.Praza@Sun.COM }
47497887SLiane.Praza@Sun.COM 
47507887SLiane.Praza@Sun.COM static const char *
_get_ev1_val(scf_tmpl_error_t * err)47517887SLiane.Praza@Sun.COM _get_ev1_val(scf_tmpl_error_t *err)
47527887SLiane.Praza@Sun.COM {
47537887SLiane.Praza@Sun.COM 	assert(err != NULL);
47547887SLiane.Praza@Sun.COM 	return (err->te_ev1);
47557887SLiane.Praza@Sun.COM }
47567887SLiane.Praza@Sun.COM 
47577887SLiane.Praza@Sun.COM static const char *
_get_ev2_val(scf_tmpl_error_t * err)47587887SLiane.Praza@Sun.COM _get_ev2_val(scf_tmpl_error_t *err)
47597887SLiane.Praza@Sun.COM {
47607887SLiane.Praza@Sun.COM 	assert(err != NULL);
47617887SLiane.Praza@Sun.COM 	return (err->te_ev2);
47627887SLiane.Praza@Sun.COM }
47637887SLiane.Praza@Sun.COM 
47647887SLiane.Praza@Sun.COM static const char *
_get_actual_val(scf_tmpl_error_t * err)47657887SLiane.Praza@Sun.COM _get_actual_val(scf_tmpl_error_t *err)
47667887SLiane.Praza@Sun.COM {
47677887SLiane.Praza@Sun.COM 	assert(err != NULL);
47687887SLiane.Praza@Sun.COM 	return (err->te_actual);
47697887SLiane.Praza@Sun.COM }
47707887SLiane.Praza@Sun.COM 
47717887SLiane.Praza@Sun.COM static const char *
_get_tmpl_fmri_val(scf_tmpl_error_t * err)47727887SLiane.Praza@Sun.COM _get_tmpl_fmri_val(scf_tmpl_error_t *err)
47737887SLiane.Praza@Sun.COM {
47747887SLiane.Praza@Sun.COM 	assert(err != NULL);
47757887SLiane.Praza@Sun.COM 	return (err->te_tmpl_fmri);
47767887SLiane.Praza@Sun.COM }
47777887SLiane.Praza@Sun.COM 
47787887SLiane.Praza@Sun.COM static const char *
_get_tmpl_pg_name_val(scf_tmpl_error_t * err)47797887SLiane.Praza@Sun.COM _get_tmpl_pg_name_val(scf_tmpl_error_t *err)
47807887SLiane.Praza@Sun.COM {
47817887SLiane.Praza@Sun.COM 	assert(err != NULL);
47827887SLiane.Praza@Sun.COM 	return (err->te_tmpl_pg_name);
47837887SLiane.Praza@Sun.COM }
47847887SLiane.Praza@Sun.COM 
47857887SLiane.Praza@Sun.COM static const char *
_get_tmpl_pg_type_val(scf_tmpl_error_t * err)47867887SLiane.Praza@Sun.COM _get_tmpl_pg_type_val(scf_tmpl_error_t *err)
47877887SLiane.Praza@Sun.COM {
47887887SLiane.Praza@Sun.COM 	assert(err != NULL);
47897887SLiane.Praza@Sun.COM 	return (err->te_tmpl_pg_type);
47907887SLiane.Praza@Sun.COM }
47917887SLiane.Praza@Sun.COM 
47927887SLiane.Praza@Sun.COM static const char *
_get_tmpl_prop_name_val(scf_tmpl_error_t * err)47937887SLiane.Praza@Sun.COM _get_tmpl_prop_name_val(scf_tmpl_error_t *err)
47947887SLiane.Praza@Sun.COM {
47957887SLiane.Praza@Sun.COM 	assert(err != NULL);
47967887SLiane.Praza@Sun.COM 	return (err->te_tmpl_prop_name);
47977887SLiane.Praza@Sun.COM }
47987887SLiane.Praza@Sun.COM 
47997887SLiane.Praza@Sun.COM static const char *
_get_tmpl_prop_type_val(scf_tmpl_error_t * err)48007887SLiane.Praza@Sun.COM _get_tmpl_prop_type_val(scf_tmpl_error_t *err)
48017887SLiane.Praza@Sun.COM {
48027887SLiane.Praza@Sun.COM 	assert(err != NULL);
48037887SLiane.Praza@Sun.COM 	return (err->te_tmpl_prop_type);
48047887SLiane.Praza@Sun.COM }
48057887SLiane.Praza@Sun.COM 
48067887SLiane.Praza@Sun.COM /*
48077887SLiane.Praza@Sun.COM  * Templates error item retrival functions
48087887SLiane.Praza@Sun.COM  */
48097887SLiane.Praza@Sun.COM typedef const char *(*get_em)(scf_tmpl_error_t *);
48107887SLiane.Praza@Sun.COM 
48117887SLiane.Praza@Sun.COM /*
48127887SLiane.Praza@Sun.COM  * if new items (lines) are added to the templates error messages,
48137887SLiane.Praza@Sun.COM  * new entries in this array (and new fuctions) will be required.
48147887SLiane.Praza@Sun.COM  */
48157887SLiane.Praza@Sun.COM static struct _tmpl_error_access {
48167887SLiane.Praza@Sun.COM 	get_em get_desc;
48177887SLiane.Praza@Sun.COM 	get_em get_val;
48187887SLiane.Praza@Sun.COM } _tmpl_error_items[] = {
48197887SLiane.Praza@Sun.COM 	{ (get_em)_get_fmri_desc, (get_em)_get_fmri_val },
48207887SLiane.Praza@Sun.COM 	{ (get_em)_get_pg_name_desc, (get_em)_get_pg_name_val },
48217887SLiane.Praza@Sun.COM 	{ (get_em)_get_prop_name_desc, (get_em)_get_prop_name_val },
48227887SLiane.Praza@Sun.COM 	{ (get_em)_get_ev1_desc, (get_em)_get_ev1_val },
48237887SLiane.Praza@Sun.COM 	{ (get_em)_get_ev2_desc, (get_em)_get_ev2_val },
48247887SLiane.Praza@Sun.COM 	{ (get_em)_get_actual_desc, (get_em)_get_actual_val },
48257887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_fmri_desc, (get_em)_get_tmpl_fmri_val },
48267887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_pg_name_desc, (get_em)_get_tmpl_pg_name_val },
48277887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_pg_type_desc, (get_em)_get_tmpl_pg_type_val },
48287887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_prop_name_desc, (get_em)_get_tmpl_prop_name_val },
48297887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_prop_type_desc, (get_em)_get_tmpl_prop_type_val },
48307887SLiane.Praza@Sun.COM 	{ NULL }
48317887SLiane.Praza@Sun.COM };
48327887SLiane.Praza@Sun.COM 
48337887SLiane.Praza@Sun.COM /*
48347887SLiane.Praza@Sun.COM  * Allocate a new scf_tmpl_error_t and add it to the errs list provided.
48357887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
48367887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
48377887SLiane.Praza@Sun.COM  */
48387887SLiane.Praza@Sun.COM static scf_tmpl_error_t *
_create_error(scf_tmpl_errors_t * errs)48397887SLiane.Praza@Sun.COM _create_error(scf_tmpl_errors_t *errs)
48407887SLiane.Praza@Sun.COM {
48417887SLiane.Praza@Sun.COM 	scf_tmpl_error_t *ret;
48427887SLiane.Praza@Sun.COM 	scf_tmpl_error_t **saved_errs;
48437887SLiane.Praza@Sun.COM 
48447887SLiane.Praza@Sun.COM 	assert(errs != NULL);
48457887SLiane.Praza@Sun.COM 	ret = calloc(1, sizeof (scf_tmpl_error_t));
48467887SLiane.Praza@Sun.COM 	if (ret == NULL) {
48477887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
48487887SLiane.Praza@Sun.COM 		return (NULL);
48497887SLiane.Praza@Sun.COM 	}
48507887SLiane.Praza@Sun.COM 
48517887SLiane.Praza@Sun.COM 	ret->te_errs = errs;
48527887SLiane.Praza@Sun.COM 
48537887SLiane.Praza@Sun.COM 	assert(errs->tes_num_errs <= errs->tes_errs_size);
48547887SLiane.Praza@Sun.COM 	if (errs->tes_num_errs == errs->tes_errs_size) {
48557887SLiane.Praza@Sun.COM 		/* Time to grow the pointer array. */
48567887SLiane.Praza@Sun.COM 		saved_errs = errs->tes_errs;
48577887SLiane.Praza@Sun.COM 		errs->tes_errs = calloc(2 * errs->tes_errs_size,
48587887SLiane.Praza@Sun.COM 		    sizeof (scf_tmpl_error_t *));
48597887SLiane.Praza@Sun.COM 		if (errs->tes_errs == NULL) {
48607887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
48617887SLiane.Praza@Sun.COM 			errs->tes_errs = saved_errs;
48627887SLiane.Praza@Sun.COM 			free(ret);
48637887SLiane.Praza@Sun.COM 			return (NULL);
48647887SLiane.Praza@Sun.COM 		}
48657887SLiane.Praza@Sun.COM 		(void) memcpy(errs->tes_errs, saved_errs, errs->tes_errs_size *
48667887SLiane.Praza@Sun.COM 		    sizeof (scf_tmpl_error_t *));
48677887SLiane.Praza@Sun.COM 		errs->tes_errs_size = 2 * errs->tes_errs_size;
48687887SLiane.Praza@Sun.COM 		free(saved_errs);
48697887SLiane.Praza@Sun.COM 	}
48707887SLiane.Praza@Sun.COM 
48717887SLiane.Praza@Sun.COM 	errs->tes_errs[errs->tes_num_errs] = ret;
48727887SLiane.Praza@Sun.COM 	errs->tes_num_errs++;
48737887SLiane.Praza@Sun.COM 
48747887SLiane.Praza@Sun.COM 	return (ret);
48757887SLiane.Praza@Sun.COM }
48767887SLiane.Praza@Sun.COM 
48777887SLiane.Praza@Sun.COM /*
48787887SLiane.Praza@Sun.COM  *
48797887SLiane.Praza@Sun.COM  * If destroy_strings is set, scf_tmpl_errors_destroy will free the
48807887SLiane.Praza@Sun.COM  * strings in scf_tmpl_error_t entries.
48817887SLiane.Praza@Sun.COM  *
48827887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
48837887SLiane.Praza@Sun.COM  *    SCF_ERROR_NO_MEMORY
48847887SLiane.Praza@Sun.COM  */
48857887SLiane.Praza@Sun.COM scf_tmpl_errors_t *
_scf_create_errors(const char * fmri,int destroy_strings)48867887SLiane.Praza@Sun.COM _scf_create_errors(const char *fmri, int destroy_strings)
48877887SLiane.Praza@Sun.COM {
48887887SLiane.Praza@Sun.COM 	scf_tmpl_errors_t *ret;
48897887SLiane.Praza@Sun.COM 	int errs_size = 20;
48907887SLiane.Praza@Sun.COM 
48917887SLiane.Praza@Sun.COM 	assert(fmri != NULL);
48927887SLiane.Praza@Sun.COM 
48937887SLiane.Praza@Sun.COM 	ret = calloc(1, sizeof (scf_tmpl_errors_t));
48947887SLiane.Praza@Sun.COM 	if (ret == NULL) {
48957887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
48967887SLiane.Praza@Sun.COM 		return (NULL);
48977887SLiane.Praza@Sun.COM 	}
48987887SLiane.Praza@Sun.COM 
48997887SLiane.Praza@Sun.COM 	ret->tes_index = 0;
49007887SLiane.Praza@Sun.COM 	ret->tes_num_errs = 0;
49017887SLiane.Praza@Sun.COM 	if ((ret->tes_fmri = strdup(fmri)) == NULL) {
49027887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
49037887SLiane.Praza@Sun.COM 		free(ret);
49047887SLiane.Praza@Sun.COM 		return (NULL);
49057887SLiane.Praza@Sun.COM 	}
49067887SLiane.Praza@Sun.COM 
49077887SLiane.Praza@Sun.COM 	ret->tes_prefix = strdup("");
49087887SLiane.Praza@Sun.COM 	if (ret->tes_prefix == NULL) {
49097887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
49107887SLiane.Praza@Sun.COM 		free((char *)ret->tes_fmri);
49117887SLiane.Praza@Sun.COM 		free(ret);
49127887SLiane.Praza@Sun.COM 		return (NULL);
49137887SLiane.Praza@Sun.COM 	}
49147887SLiane.Praza@Sun.COM 	ret->tes_flag = destroy_strings;
49157887SLiane.Praza@Sun.COM 
49167887SLiane.Praza@Sun.COM 	/* Make space for a few errors. */
49177887SLiane.Praza@Sun.COM 	ret->tes_errs = calloc(errs_size, sizeof (scf_tmpl_error_t *));
49187887SLiane.Praza@Sun.COM 	if (ret->tes_errs == NULL) {
49197887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
49207887SLiane.Praza@Sun.COM 		free((char *)ret->tes_fmri);
49217887SLiane.Praza@Sun.COM 		free((char *)ret->tes_prefix);
49227887SLiane.Praza@Sun.COM 		free(ret);
49237887SLiane.Praza@Sun.COM 		return (NULL);
49247887SLiane.Praza@Sun.COM 	}
49257887SLiane.Praza@Sun.COM 	ret->tes_errs_size = errs_size;
49267887SLiane.Praza@Sun.COM 
49277887SLiane.Praza@Sun.COM 	return (ret);
49287887SLiane.Praza@Sun.COM }
49297887SLiane.Praza@Sun.COM 
49307887SLiane.Praza@Sun.COM /*
49317887SLiane.Praza@Sun.COM  * return 0 on success, if fails set scf_error() to:
49327887SLiane.Praza@Sun.COM  *
49337887SLiane.Praza@Sun.COM  *    SCF_ERROR_NO_MEMORY
49347887SLiane.Praza@Sun.COM  */
49357887SLiane.Praza@Sun.COM int
_scf_tmpl_error_set_prefix(scf_tmpl_errors_t * errs,const char * prefix)49367887SLiane.Praza@Sun.COM _scf_tmpl_error_set_prefix(scf_tmpl_errors_t *errs, const char *prefix)
49377887SLiane.Praza@Sun.COM {
49387887SLiane.Praza@Sun.COM 	free((void *) errs->tes_prefix);
49397887SLiane.Praza@Sun.COM 	if (prefix == NULL)
49407887SLiane.Praza@Sun.COM 		errs->tes_prefix = strdup("");
49417887SLiane.Praza@Sun.COM 	else
49427887SLiane.Praza@Sun.COM 		errs->tes_prefix = strdup(prefix);
49437887SLiane.Praza@Sun.COM 	if (errs->tes_prefix == NULL) {
49447887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
49457887SLiane.Praza@Sun.COM 		return (-1);
49467887SLiane.Praza@Sun.COM 	}
49477887SLiane.Praza@Sun.COM 	return (0);
49487887SLiane.Praza@Sun.COM }
49497887SLiane.Praza@Sun.COM 
49507887SLiane.Praza@Sun.COM /*
49517887SLiane.Praza@Sun.COM  *
49527887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
49537887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
49547887SLiane.Praza@Sun.COM  */
49557887SLiane.Praza@Sun.COM int
_scf_tmpl_add_error(scf_tmpl_errors_t * errs,scf_tmpl_error_type_t type,const char * pg_name,const char * prop_name,const char * ev1,const char * ev2,const char * actual,const char * tmpl_fmri,const char * tmpl_pg_name,const char * tmpl_pg_type,const char * tmpl_prop_name,const char * tmpl_prop_type)49567887SLiane.Praza@Sun.COM _scf_tmpl_add_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
49577887SLiane.Praza@Sun.COM     const char *pg_name, const char *prop_name,
49587887SLiane.Praza@Sun.COM     const char *ev1, const char *ev2, const char *actual,
49597887SLiane.Praza@Sun.COM     const char *tmpl_fmri, const char *tmpl_pg_name, const char *tmpl_pg_type,
49607887SLiane.Praza@Sun.COM     const char *tmpl_prop_name, const char *tmpl_prop_type)
49617887SLiane.Praza@Sun.COM {
49627887SLiane.Praza@Sun.COM 	scf_tmpl_error_t *err;
49637887SLiane.Praza@Sun.COM 
49647887SLiane.Praza@Sun.COM 	assert(errs != NULL);
49657887SLiane.Praza@Sun.COM 	assert(tmpl_fmri != NULL);
49667887SLiane.Praza@Sun.COM 
49677887SLiane.Praza@Sun.COM 	err = _create_error(errs);
49687887SLiane.Praza@Sun.COM 	if (err == NULL)
49697887SLiane.Praza@Sun.COM 		return (-1);
49707887SLiane.Praza@Sun.COM 
49717887SLiane.Praza@Sun.COM 	err->te_type = type;
49727887SLiane.Praza@Sun.COM 	err->te_pg_name = pg_name;
49737887SLiane.Praza@Sun.COM 	err->te_prop_name = prop_name;
49747887SLiane.Praza@Sun.COM 	err->te_ev1 = ev1;
49757887SLiane.Praza@Sun.COM 	err->te_ev2 = ev2;
49767887SLiane.Praza@Sun.COM 	err->te_actual = actual;
49777887SLiane.Praza@Sun.COM 	err->te_tmpl_fmri = tmpl_fmri;
49787887SLiane.Praza@Sun.COM 	err->te_tmpl_pg_name = tmpl_pg_name;
49797887SLiane.Praza@Sun.COM 	err->te_tmpl_pg_type = tmpl_pg_type;
49807887SLiane.Praza@Sun.COM 	err->te_tmpl_prop_name = tmpl_prop_name;
49817887SLiane.Praza@Sun.COM 	err->te_tmpl_prop_type = tmpl_prop_type;
49827887SLiane.Praza@Sun.COM 
49837887SLiane.Praza@Sun.COM 	return (0);
49847887SLiane.Praza@Sun.COM }
49857887SLiane.Praza@Sun.COM 
49867887SLiane.Praza@Sun.COM /*
49877887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed with free()
49887887SLiane.Praza@Sun.COM  * string contains converted 64-bit integer value
49897887SLiane.Praza@Sun.COM  * flag set for signed values
49907887SLiane.Praza@Sun.COM  * if fails return NULL and set scf_error() to:
49917887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
49927887SLiane.Praza@Sun.COM  */
49937887SLiane.Praza@Sun.COM static char *
_val_to_string(uint64_t val,int flag)49947887SLiane.Praza@Sun.COM _val_to_string(uint64_t val, int flag)
49957887SLiane.Praza@Sun.COM {
49967887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
49977887SLiane.Praza@Sun.COM 	char *buf;
49987887SLiane.Praza@Sun.COM 
49997887SLiane.Praza@Sun.COM 	buf = malloc(sz);
50007887SLiane.Praza@Sun.COM 	if (buf == NULL) {
50017887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
50027887SLiane.Praza@Sun.COM 		return (NULL);
50037887SLiane.Praza@Sun.COM 	}
50047887SLiane.Praza@Sun.COM 
50057887SLiane.Praza@Sun.COM 	if (flag == 0)
50067887SLiane.Praza@Sun.COM 		(void) snprintf(buf, sz, "%" PRIu64, val);
50077887SLiane.Praza@Sun.COM 	else
50087887SLiane.Praza@Sun.COM 		(void) snprintf(buf, sz, "%" PRIi64, (int64_t)val);
50097887SLiane.Praza@Sun.COM 
50107887SLiane.Praza@Sun.COM 	return (buf);
50117887SLiane.Praza@Sun.COM }
50127887SLiane.Praza@Sun.COM 
50137887SLiane.Praza@Sun.COM /*
50147887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
50157887SLiane.Praza@Sun.COM  * set scf_error() to:
50167887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
50177887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
50187887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
50197887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
50207887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
50217887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
50227887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
50237887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
50247887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
50257887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
50267887SLiane.Praza@Sun.COM  */
50277887SLiane.Praza@Sun.COM static int
_add_tmpl_missing_pg_error(scf_tmpl_errors_t * errs,scf_pg_tmpl_t * t)50287887SLiane.Praza@Sun.COM _add_tmpl_missing_pg_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t)
50297887SLiane.Praza@Sun.COM {
50307887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
50317887SLiane.Praza@Sun.COM 	char *ev2 = NULL;
50327887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
50337887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
50347887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
50357887SLiane.Praza@Sun.COM 
50367887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL)
50377887SLiane.Praza@Sun.COM 		return (-1);
50387887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &t_pg_name) == -1) {
50397887SLiane.Praza@Sun.COM 		goto cleanup;
50407887SLiane.Praza@Sun.COM 	}
50417887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &t_pg_type) == -1) {
50427887SLiane.Praza@Sun.COM 		goto cleanup;
50437887SLiane.Praza@Sun.COM 	}
50447887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_pg_name)) == NULL) {
50457887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
50467887SLiane.Praza@Sun.COM 		goto cleanup;
50477887SLiane.Praza@Sun.COM 	}
50487887SLiane.Praza@Sun.COM 	if ((ev2 = strdup(t_pg_type)) == NULL) {
50497887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
50507887SLiane.Praza@Sun.COM 		goto cleanup;
50517887SLiane.Praza@Sun.COM 	}
50527887SLiane.Praza@Sun.COM 
50537887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PG, NULL, NULL, ev1,
50547887SLiane.Praza@Sun.COM 	    ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL));
50557887SLiane.Praza@Sun.COM cleanup:
50567887SLiane.Praza@Sun.COM 	free(ev1);
50577887SLiane.Praza@Sun.COM 	free(ev2);
50587887SLiane.Praza@Sun.COM 	free(t_fmri);
50597887SLiane.Praza@Sun.COM 	free(t_pg_name);
50607887SLiane.Praza@Sun.COM 	free(t_pg_type);
50617887SLiane.Praza@Sun.COM 	return (-1);
50627887SLiane.Praza@Sun.COM }
50637887SLiane.Praza@Sun.COM 
50647887SLiane.Praza@Sun.COM /*
50657887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
50667887SLiane.Praza@Sun.COM  * set scf_error() to:
50677887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
50687887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
50697887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
50707887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
50717887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
50727887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
50737887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
50747887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
50757887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
50767887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
50777887SLiane.Praza@Sun.COM  */
50787887SLiane.Praza@Sun.COM static int
_add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t * errs,scf_pg_tmpl_t * t,scf_propertygroup_t * pg)50797887SLiane.Praza@Sun.COM _add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t,
50807887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg)
50817887SLiane.Praza@Sun.COM {
50827887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
50837887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
50847887SLiane.Praza@Sun.COM 	char *actual = NULL;
50857887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
50867887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
50877887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
50887887SLiane.Praza@Sun.COM 
50897887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL)
50907887SLiane.Praza@Sun.COM 		return (-1);
50917887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(pg)) == NULL)
50927887SLiane.Praza@Sun.COM 		goto cleanup;
50937887SLiane.Praza@Sun.COM 	if ((actual = _scf_get_pg_type(pg)) == NULL)
50947887SLiane.Praza@Sun.COM 		goto cleanup;
50957887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &t_pg_name) == -1) {
50967887SLiane.Praza@Sun.COM 		goto cleanup;
50977887SLiane.Praza@Sun.COM 	}
50987887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &t_pg_type) == -1) {
50997887SLiane.Praza@Sun.COM 		goto cleanup;
51007887SLiane.Praza@Sun.COM 	}
51017887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_pg_type)) == NULL) {
51027887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
51037887SLiane.Praza@Sun.COM 		goto cleanup;
51047887SLiane.Praza@Sun.COM 	}
51057887SLiane.Praza@Sun.COM 
51067887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PG_TYPE, pg_name, NULL,
51077887SLiane.Praza@Sun.COM 	    ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type, NULL, NULL));
51087887SLiane.Praza@Sun.COM cleanup:
51097887SLiane.Praza@Sun.COM 	free(pg_name);
51107887SLiane.Praza@Sun.COM 	free(ev1);
51117887SLiane.Praza@Sun.COM 	free(actual);
51127887SLiane.Praza@Sun.COM 	free(t_fmri);
51137887SLiane.Praza@Sun.COM 	free(t_pg_name);
51147887SLiane.Praza@Sun.COM 	free(t_pg_type);
51157887SLiane.Praza@Sun.COM 	return (-1);
51167887SLiane.Praza@Sun.COM }
51177887SLiane.Praza@Sun.COM 
51187887SLiane.Praza@Sun.COM /*
51197887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
51207887SLiane.Praza@Sun.COM  * set scf_error() to:
51217887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
51227887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
51237887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
51247887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
51257887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
51267887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
51277887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
51287887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
51297887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
51307887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
51317887SLiane.Praza@Sun.COM  */
51327887SLiane.Praza@Sun.COM static int
_add_tmpl_missing_prop_error(scf_tmpl_errors_t * errs,scf_pg_tmpl_t * t,scf_propertygroup_t * pg,const scf_prop_tmpl_t * pt)51337887SLiane.Praza@Sun.COM _add_tmpl_missing_prop_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t,
51347887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt)
51357887SLiane.Praza@Sun.COM {
51367887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
51377887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
51387887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
51397887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
51407887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
51417887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
51427887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
51437887SLiane.Praza@Sun.COM 
51447887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL)
51457887SLiane.Praza@Sun.COM 		return (-1);
51467887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(pg)) == NULL)
51477887SLiane.Praza@Sun.COM 		goto cleanup;
51487887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &t_pg_name) == -1) {
51497887SLiane.Praza@Sun.COM 		goto cleanup;
51507887SLiane.Praza@Sun.COM 	}
51517887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &t_pg_type) == -1) {
51527887SLiane.Praza@Sun.COM 		goto cleanup;
51537887SLiane.Praza@Sun.COM 	}
51547887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
51557887SLiane.Praza@Sun.COM 		goto cleanup;
51567887SLiane.Praza@Sun.COM 	}
51577887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
51587887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
51597887SLiane.Praza@Sun.COM 		free(t_prop_type);
51607887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
51617887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
51627887SLiane.Praza@Sun.COM 		goto cleanup;
51637887SLiane.Praza@Sun.COM 	}
51647887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
51657887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
51667887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
51677887SLiane.Praza@Sun.COM 			goto cleanup;
51687887SLiane.Praza@Sun.COM 		}
51697887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_prop_name)) == NULL) {
51707887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
51717887SLiane.Praza@Sun.COM 		goto cleanup;
51727887SLiane.Praza@Sun.COM 	}
51737887SLiane.Praza@Sun.COM 
51747887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PROP, pg_name, NULL,
51757887SLiane.Praza@Sun.COM 	    ev1, NULL, NULL, t_fmri, t_pg_name, t_pg_type, t_prop_name,
51767887SLiane.Praza@Sun.COM 	    t_prop_type));
51777887SLiane.Praza@Sun.COM cleanup:
51787887SLiane.Praza@Sun.COM 	free(pg_name);
51797887SLiane.Praza@Sun.COM 	free(ev1);
51807887SLiane.Praza@Sun.COM 	free(t_fmri);
51817887SLiane.Praza@Sun.COM 	free(t_pg_name);
51827887SLiane.Praza@Sun.COM 	free(t_pg_type);
51837887SLiane.Praza@Sun.COM 	free(t_prop_name);
51847887SLiane.Praza@Sun.COM 	free(t_prop_type);
51857887SLiane.Praza@Sun.COM 	return (-1);
51867887SLiane.Praza@Sun.COM }
51877887SLiane.Praza@Sun.COM 
51887887SLiane.Praza@Sun.COM /*
51897887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
51907887SLiane.Praza@Sun.COM  * set scf_error() to:
51917887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
51927887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
51937887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
51947887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
51957887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
51967887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
51977887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
51987887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
51997887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
52007887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
52017887SLiane.Praza@Sun.COM  */
52027887SLiane.Praza@Sun.COM static int
_add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t * errs,scf_propertygroup_t * pg,const scf_prop_tmpl_t * pt,scf_property_t * prop)52037887SLiane.Praza@Sun.COM _add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t *errs,
52047887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop)
52057887SLiane.Praza@Sun.COM {
52067887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
52077887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
52087887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
52097887SLiane.Praza@Sun.COM 	char *actual = NULL;
52107887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
52117887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
52127887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
52137887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
52147887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
52157887SLiane.Praza@Sun.COM 
52167887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
52177887SLiane.Praza@Sun.COM 		return (-1);
52187887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(pg)) == NULL)
52197887SLiane.Praza@Sun.COM 		goto cleanup;
52207887SLiane.Praza@Sun.COM 	if ((prop_name = _scf_get_prop_name(prop)) == NULL)
52217887SLiane.Praza@Sun.COM 		goto cleanup;
52227887SLiane.Praza@Sun.COM 	if ((actual = _scf_get_prop_type(prop)) == NULL)
52237887SLiane.Praza@Sun.COM 		goto cleanup;
52247887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
52257887SLiane.Praza@Sun.COM 		goto cleanup;
52267887SLiane.Praza@Sun.COM 	}
52277887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
52287887SLiane.Praza@Sun.COM 		goto cleanup;
52297887SLiane.Praza@Sun.COM 	}
52307887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
52317887SLiane.Praza@Sun.COM 		goto cleanup;
52327887SLiane.Praza@Sun.COM 	}
52337887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
52347887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
52357887SLiane.Praza@Sun.COM 		free(t_prop_type);
52367887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
52377887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
52387887SLiane.Praza@Sun.COM 		goto cleanup;
52397887SLiane.Praza@Sun.COM 	}
52407887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
52417887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
52427887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
52437887SLiane.Praza@Sun.COM 			goto cleanup;
52447887SLiane.Praza@Sun.COM 		}
52457887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_prop_type)) == NULL) {
52467887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
52477887SLiane.Praza@Sun.COM 		goto cleanup;
52487887SLiane.Praza@Sun.COM 	}
52497887SLiane.Praza@Sun.COM 
52507887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PROP_TYPE, pg_name,
52517887SLiane.Praza@Sun.COM 	    prop_name, ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type,
52527887SLiane.Praza@Sun.COM 	    t_prop_name, t_prop_type));
52537887SLiane.Praza@Sun.COM cleanup:
52547887SLiane.Praza@Sun.COM 	free(pg_name);
52557887SLiane.Praza@Sun.COM 	free(prop_name);
52567887SLiane.Praza@Sun.COM 	free(ev1);
52577887SLiane.Praza@Sun.COM 	free(actual);
52587887SLiane.Praza@Sun.COM 	free(t_fmri);
52597887SLiane.Praza@Sun.COM 	free(t_pg_name);
52607887SLiane.Praza@Sun.COM 	free(t_pg_type);
52617887SLiane.Praza@Sun.COM 	free(t_prop_name);
52627887SLiane.Praza@Sun.COM 	free(t_prop_type);
52637887SLiane.Praza@Sun.COM 	return (-1);
52647887SLiane.Praza@Sun.COM }
52657887SLiane.Praza@Sun.COM 
52667887SLiane.Praza@Sun.COM /*
52677887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
52687887SLiane.Praza@Sun.COM  * set scf_error() to:
52697887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
52707887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
52717887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
52727887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
52737887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
52747887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
52757887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
52767887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
52777887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
52787887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
52797887SLiane.Praza@Sun.COM  */
52807887SLiane.Praza@Sun.COM static int
_add_tmpl_count_error(scf_tmpl_errors_t * errs,scf_tmpl_error_type_t type,scf_propertygroup_t * pg,const scf_prop_tmpl_t * pt,scf_property_t * prop,uint64_t count,uint64_t * min,uint64_t * max)52817887SLiane.Praza@Sun.COM _add_tmpl_count_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
52827887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop,
52837887SLiane.Praza@Sun.COM     uint64_t count, uint64_t *min, uint64_t *max)
52847887SLiane.Praza@Sun.COM {
52857887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
52867887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
52877887SLiane.Praza@Sun.COM 	char *s_min = NULL;
52887887SLiane.Praza@Sun.COM 	char *s_max = NULL;
52897887SLiane.Praza@Sun.COM 	char *num = NULL;
52907887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
52917887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
52927887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
52937887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
52947887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
52957887SLiane.Praza@Sun.COM 
52967887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
52977887SLiane.Praza@Sun.COM 		return (-1);
52987887SLiane.Praza@Sun.COM 	switch (type) {
52997887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
53007887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
53017887SLiane.Praza@Sun.COM 		if ((pg_name = _scf_get_pg_name(pg)) == NULL)
53027887SLiane.Praza@Sun.COM 			goto cleanup;
53037887SLiane.Praza@Sun.COM 		if ((prop_name = _scf_get_prop_name(prop)) == NULL)
53047887SLiane.Praza@Sun.COM 			goto cleanup;
53057887SLiane.Praza@Sun.COM 		break;
53067887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
53077887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
53087887SLiane.Praza@Sun.COM 		break;
53097887SLiane.Praza@Sun.COM 	}
53107887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
53117887SLiane.Praza@Sun.COM 		goto cleanup;
53127887SLiane.Praza@Sun.COM 	}
53137887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
53147887SLiane.Praza@Sun.COM 		goto cleanup;
53157887SLiane.Praza@Sun.COM 	}
53167887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
53177887SLiane.Praza@Sun.COM 		goto cleanup;
53187887SLiane.Praza@Sun.COM 	}
53197887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
53207887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
53217887SLiane.Praza@Sun.COM 		free(t_prop_type);
53227887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
53237887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
53247887SLiane.Praza@Sun.COM 		goto cleanup;
53257887SLiane.Praza@Sun.COM 	}
53267887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
53277887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
53287887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
53297887SLiane.Praza@Sun.COM 			goto cleanup;
53307887SLiane.Praza@Sun.COM 		}
53317887SLiane.Praza@Sun.COM 	if (min == NULL) {
53327887SLiane.Praza@Sun.COM 		if ((s_min = strdup("")) == NULL) {
53337887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
53347887SLiane.Praza@Sun.COM 			goto cleanup;
53357887SLiane.Praza@Sun.COM 		}
53367887SLiane.Praza@Sun.COM 	} else {
53377887SLiane.Praza@Sun.COM 		if ((s_min = _val_to_string(*min, 0)) == NULL) {
53387887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
53397887SLiane.Praza@Sun.COM 			goto cleanup;
53407887SLiane.Praza@Sun.COM 		}
53417887SLiane.Praza@Sun.COM 	}
53427887SLiane.Praza@Sun.COM 	if (max == NULL) {
53437887SLiane.Praza@Sun.COM 		if ((s_max = strdup("")) == NULL) {
53447887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
53457887SLiane.Praza@Sun.COM 			goto cleanup;
53467887SLiane.Praza@Sun.COM 		}
53477887SLiane.Praza@Sun.COM 	} else {
53487887SLiane.Praza@Sun.COM 		if ((s_max = _val_to_string(*max, 0)) == NULL) {
53497887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
53507887SLiane.Praza@Sun.COM 			goto cleanup;
53517887SLiane.Praza@Sun.COM 		}
53527887SLiane.Praza@Sun.COM 	}
53537887SLiane.Praza@Sun.COM 	if ((num = _val_to_string(count, 0)) == NULL) {
53547887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
53557887SLiane.Praza@Sun.COM 		goto cleanup;
53567887SLiane.Praza@Sun.COM 	}
53577887SLiane.Praza@Sun.COM 
53587887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min,
53597887SLiane.Praza@Sun.COM 	    s_max, num, t_fmri, t_pg_name, t_pg_type, t_prop_name,
53607887SLiane.Praza@Sun.COM 	    t_prop_type));
53617887SLiane.Praza@Sun.COM cleanup:
53627887SLiane.Praza@Sun.COM 	free(pg_name);
53637887SLiane.Praza@Sun.COM 	free(prop_name);
53647887SLiane.Praza@Sun.COM 	free(s_min);
53657887SLiane.Praza@Sun.COM 	free(s_max);
53667887SLiane.Praza@Sun.COM 	free(num);
53677887SLiane.Praza@Sun.COM 	free(t_fmri);
53687887SLiane.Praza@Sun.COM 	free(t_pg_name);
53697887SLiane.Praza@Sun.COM 	free(t_pg_type);
53707887SLiane.Praza@Sun.COM 	free(t_prop_name);
53717887SLiane.Praza@Sun.COM 	free(t_prop_type);
53727887SLiane.Praza@Sun.COM 	return (-1);
53737887SLiane.Praza@Sun.COM }
53747887SLiane.Praza@Sun.COM 
53757887SLiane.Praza@Sun.COM /*
53767887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
53777887SLiane.Praza@Sun.COM  * set scf_error() to:
53787887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
53797887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
53807887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
53817887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
53827887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
53837887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
53847887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
53857887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
53867887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
53877887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
53887887SLiane.Praza@Sun.COM  */
53897887SLiane.Praza@Sun.COM static int
_add_tmpl_constraint_error(scf_tmpl_errors_t * errs,scf_tmpl_error_type_t type,scf_propertygroup_t * pg,const scf_prop_tmpl_t * pt,scf_property_t * prop,scf_value_t * val)53907887SLiane.Praza@Sun.COM _add_tmpl_constraint_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
53917887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop,
53927887SLiane.Praza@Sun.COM     scf_value_t *val)
53937887SLiane.Praza@Sun.COM {
53947887SLiane.Praza@Sun.COM 	scf_type_t val_type;
53957887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
53967887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
53977887SLiane.Praza@Sun.COM 	char *value = NULL;
53987887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
53997887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
54007887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
54017887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
54027887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
54037887SLiane.Praza@Sun.COM 
54047887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
54057887SLiane.Praza@Sun.COM 		return (-1);
54067887SLiane.Praza@Sun.COM 	switch (type) {
54077887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
54087887SLiane.Praza@Sun.COM 		if ((pg_name = _scf_get_pg_name(pg)) == NULL)
54097887SLiane.Praza@Sun.COM 			goto cleanup;
54107887SLiane.Praza@Sun.COM 		if ((prop_name = _scf_get_prop_name(prop)) == NULL)
54117887SLiane.Praza@Sun.COM 			goto cleanup;
54127887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
54137887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
54147887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
54157887SLiane.Praza@Sun.COM 		if ((value = _scf_value_get_as_string(val)) == NULL)
54167887SLiane.Praza@Sun.COM 			goto cleanup;
54177887SLiane.Praza@Sun.COM 		break;
54187887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
54197887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
54207887SLiane.Praza@Sun.COM 		/* use value for value type */
54217887SLiane.Praza@Sun.COM 		val_type = scf_value_type(val);
54227887SLiane.Praza@Sun.COM 		if ((value = strdup(scf_type_to_string(val_type))) ==
54237887SLiane.Praza@Sun.COM 		    NULL) {
54247887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
54257887SLiane.Praza@Sun.COM 			goto cleanup;
54267887SLiane.Praza@Sun.COM 		}
54277887SLiane.Praza@Sun.COM 		break;
54287887SLiane.Praza@Sun.COM 	}
54297887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
54307887SLiane.Praza@Sun.COM 		goto cleanup;
54317887SLiane.Praza@Sun.COM 	}
54327887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
54337887SLiane.Praza@Sun.COM 		goto cleanup;
54347887SLiane.Praza@Sun.COM 	}
54357887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
54367887SLiane.Praza@Sun.COM 		goto cleanup;
54377887SLiane.Praza@Sun.COM 	}
54387887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
54397887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
54407887SLiane.Praza@Sun.COM 		free(t_prop_type);
54417887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
54427887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
54437887SLiane.Praza@Sun.COM 		goto cleanup;
54447887SLiane.Praza@Sun.COM 	}
54457887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
54467887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
54477887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
54487887SLiane.Praza@Sun.COM 			goto cleanup;
54497887SLiane.Praza@Sun.COM 		}
54507887SLiane.Praza@Sun.COM 
54517887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, NULL, NULL,
54527887SLiane.Praza@Sun.COM 	    value, t_fmri, t_pg_name, t_pg_type, t_prop_name, t_prop_type));
54537887SLiane.Praza@Sun.COM cleanup:
54547887SLiane.Praza@Sun.COM 	assert(scf_error() != SCF_ERROR_NOT_SET);
54557887SLiane.Praza@Sun.COM 	free(pg_name);
54567887SLiane.Praza@Sun.COM 	free(prop_name);
54577887SLiane.Praza@Sun.COM 	free(value);
54587887SLiane.Praza@Sun.COM 	free(t_fmri);
54597887SLiane.Praza@Sun.COM 	free(t_pg_name);
54607887SLiane.Praza@Sun.COM 	free(t_pg_type);
54617887SLiane.Praza@Sun.COM 	free(t_prop_name);
54627887SLiane.Praza@Sun.COM 	free(t_prop_type);
54637887SLiane.Praza@Sun.COM 	return (-1);
54647887SLiane.Praza@Sun.COM }
54657887SLiane.Praza@Sun.COM 
54667887SLiane.Praza@Sun.COM /*
54677887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
54687887SLiane.Praza@Sun.COM  * set scf_error() to:
54697887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
54707887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
54717887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
54727887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
54737887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
54747887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
54757887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
54767887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
54777887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
54787887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
54797887SLiane.Praza@Sun.COM  */
54807887SLiane.Praza@Sun.COM static int
_add_tmpl_int_error(scf_tmpl_errors_t * errs,scf_tmpl_error_type_t type,scf_propertygroup_t * pg,const scf_prop_tmpl_t * pt,scf_property_t * prop,int64_t val,int64_t * min,int64_t * max)54817887SLiane.Praza@Sun.COM _add_tmpl_int_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
54827887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop,
54837887SLiane.Praza@Sun.COM     int64_t val, int64_t *min, int64_t *max)
54847887SLiane.Praza@Sun.COM {
54857887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
54867887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
54877887SLiane.Praza@Sun.COM 	char *s_min = NULL;
54887887SLiane.Praza@Sun.COM 	char *s_max = NULL;
54897887SLiane.Praza@Sun.COM 	char *value = NULL;
54907887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
54917887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
54927887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
54937887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
54947887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
54957887SLiane.Praza@Sun.COM 
54967887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
54977887SLiane.Praza@Sun.COM 		return (-1);
54987887SLiane.Praza@Sun.COM 
54997887SLiane.Praza@Sun.COM 	switch (type) {
55007887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
55017887SLiane.Praza@Sun.COM 		if ((pg_name = _scf_get_pg_name(pg)) == NULL)
55027887SLiane.Praza@Sun.COM 			goto cleanup;
55037887SLiane.Praza@Sun.COM 		if ((prop_name = _scf_get_prop_name(prop)) == NULL)
55047887SLiane.Praza@Sun.COM 			goto cleanup;
55057887SLiane.Praza@Sun.COM 		break;
55067887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
55077887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
55087887SLiane.Praza@Sun.COM 		break;
55097887SLiane.Praza@Sun.COM 	}
55107887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
55117887SLiane.Praza@Sun.COM 		goto cleanup;
55127887SLiane.Praza@Sun.COM 	}
55137887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
55147887SLiane.Praza@Sun.COM 		goto cleanup;
55157887SLiane.Praza@Sun.COM 	}
55167887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
55177887SLiane.Praza@Sun.COM 		goto cleanup;
55187887SLiane.Praza@Sun.COM 	}
55197887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
55207887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
55217887SLiane.Praza@Sun.COM 		free(t_prop_type);
55227887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
55237887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
55247887SLiane.Praza@Sun.COM 		goto cleanup;
55257887SLiane.Praza@Sun.COM 	}
55267887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
55277887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
55287887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
55297887SLiane.Praza@Sun.COM 			goto cleanup;
55307887SLiane.Praza@Sun.COM 		}
55317887SLiane.Praza@Sun.COM 	if (min == NULL) {
55327887SLiane.Praza@Sun.COM 		if ((s_min = strdup("")) == NULL) {
55337887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
55347887SLiane.Praza@Sun.COM 			goto cleanup;
55357887SLiane.Praza@Sun.COM 		}
55367887SLiane.Praza@Sun.COM 	} else {
55377887SLiane.Praza@Sun.COM 		if ((s_min = _val_to_string(*((uint64_t *)min), 1)) == NULL) {
55387887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
55397887SLiane.Praza@Sun.COM 			goto cleanup;
55407887SLiane.Praza@Sun.COM 		}
55417887SLiane.Praza@Sun.COM 	}
55427887SLiane.Praza@Sun.COM 	if (max == NULL) {
55437887SLiane.Praza@Sun.COM 		if ((s_max = strdup("")) == NULL) {
55447887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
55457887SLiane.Praza@Sun.COM 			goto cleanup;
55467887SLiane.Praza@Sun.COM 		}
55477887SLiane.Praza@Sun.COM 	} else {
55487887SLiane.Praza@Sun.COM 		if ((s_max = _val_to_string(*((uint64_t *)max), 1)) == NULL) {
55497887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
55507887SLiane.Praza@Sun.COM 			goto cleanup;
55517887SLiane.Praza@Sun.COM 		}
55527887SLiane.Praza@Sun.COM 	}
55537887SLiane.Praza@Sun.COM 	if ((value = _val_to_string((uint64_t)val, 1)) == NULL) {
55547887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
55557887SLiane.Praza@Sun.COM 		goto cleanup;
55567887SLiane.Praza@Sun.COM 	}
55577887SLiane.Praza@Sun.COM 
55587887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min,
55597887SLiane.Praza@Sun.COM 	    s_max, value, t_fmri, t_pg_name, t_pg_type, t_prop_name,
55607887SLiane.Praza@Sun.COM 	    t_prop_type));
55617887SLiane.Praza@Sun.COM cleanup:
55627887SLiane.Praza@Sun.COM 	free(pg_name);
55637887SLiane.Praza@Sun.COM 	free(prop_name);
55647887SLiane.Praza@Sun.COM 	free(s_min);
55657887SLiane.Praza@Sun.COM 	free(s_max);
55667887SLiane.Praza@Sun.COM 	free(value);
55677887SLiane.Praza@Sun.COM 	free(t_fmri);
55687887SLiane.Praza@Sun.COM 	free(t_pg_name);
55697887SLiane.Praza@Sun.COM 	free(t_pg_type);
55707887SLiane.Praza@Sun.COM 	free(t_prop_name);
55717887SLiane.Praza@Sun.COM 	free(t_prop_type);
55727887SLiane.Praza@Sun.COM 	return (-1);
55737887SLiane.Praza@Sun.COM }
55747887SLiane.Praza@Sun.COM 
55757887SLiane.Praza@Sun.COM /*
55767887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
55777887SLiane.Praza@Sun.COM  * set scf_error() to:
55787887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
55797887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
55807887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
55817887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
55827887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
55837887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
55847887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
55857887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
55867887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
55877887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
55887887SLiane.Praza@Sun.COM  */
55897887SLiane.Praza@Sun.COM static int
_add_tmpl_pg_redefine_error(scf_tmpl_errors_t * errs,scf_pg_tmpl_t * t,scf_pg_tmpl_t * r)55907887SLiane.Praza@Sun.COM _add_tmpl_pg_redefine_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t,
55917887SLiane.Praza@Sun.COM     scf_pg_tmpl_t *r)
55927887SLiane.Praza@Sun.COM {
55937887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
55947887SLiane.Praza@Sun.COM 	char *ev2 = NULL;
55957887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
55967887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
55977887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
55987887SLiane.Praza@Sun.COM 
55997887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(r)) == NULL)
56007887SLiane.Praza@Sun.COM 		return (-1);
56017887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(r, &t_pg_name) == -1) {
56027887SLiane.Praza@Sun.COM 		goto cleanup;
56037887SLiane.Praza@Sun.COM 	}
56047887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(r, &t_pg_type) == -1) {
56057887SLiane.Praza@Sun.COM 		goto cleanup;
56067887SLiane.Praza@Sun.COM 	}
56077887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &ev1) == -1) {
56087887SLiane.Praza@Sun.COM 		goto cleanup;
56097887SLiane.Praza@Sun.COM 	}
56107887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &ev2) == -1) {
56117887SLiane.Praza@Sun.COM 		goto cleanup;
56127887SLiane.Praza@Sun.COM 	}
56137887SLiane.Praza@Sun.COM 
56147887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_PG_REDEFINE, NULL, NULL,
56157887SLiane.Praza@Sun.COM 	    ev1, ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL));
56167887SLiane.Praza@Sun.COM cleanup:
56177887SLiane.Praza@Sun.COM 	free(ev1);
56187887SLiane.Praza@Sun.COM 	free(ev2);
56197887SLiane.Praza@Sun.COM 	free(t_fmri);
56207887SLiane.Praza@Sun.COM 	free(t_pg_name);
56217887SLiane.Praza@Sun.COM 	free(t_pg_type);
56227887SLiane.Praza@Sun.COM 	return (-1);
56237887SLiane.Praza@Sun.COM }
56247887SLiane.Praza@Sun.COM 
56257887SLiane.Praza@Sun.COM /*
56267887SLiane.Praza@Sun.COM  * return 0 if value is within count ranges constraint.
56277887SLiane.Praza@Sun.COM  * return -1 otherwise
56287887SLiane.Praza@Sun.COM  */
56297887SLiane.Praza@Sun.COM static int
_check_count_ranges(scf_count_ranges_t * cr,uint64_t v)56307887SLiane.Praza@Sun.COM _check_count_ranges(scf_count_ranges_t *cr, uint64_t v)
56317887SLiane.Praza@Sun.COM {
56327887SLiane.Praza@Sun.COM 	int i;
56337887SLiane.Praza@Sun.COM 
56347887SLiane.Praza@Sun.COM 	for (i = 0; i < cr->scr_num_ranges; ++i) {
56357887SLiane.Praza@Sun.COM 		if (v >= cr->scr_min[i] &&
56367887SLiane.Praza@Sun.COM 		    v <= cr->scr_max[i]) {
56377887SLiane.Praza@Sun.COM 			/* value is within ranges constraint */
56387887SLiane.Praza@Sun.COM 			return (0);
56397887SLiane.Praza@Sun.COM 		}
56407887SLiane.Praza@Sun.COM 	}
56417887SLiane.Praza@Sun.COM 	return (-1);
56427887SLiane.Praza@Sun.COM }
56437887SLiane.Praza@Sun.COM 
56447887SLiane.Praza@Sun.COM /*
56457887SLiane.Praza@Sun.COM  * return 0 if value is within count ranges constraint.
56467887SLiane.Praza@Sun.COM  * return -1 otherwise
56477887SLiane.Praza@Sun.COM  */
56487887SLiane.Praza@Sun.COM static int
_check_int_ranges(scf_int_ranges_t * ir,int64_t v)56497887SLiane.Praza@Sun.COM _check_int_ranges(scf_int_ranges_t *ir, int64_t v)
56507887SLiane.Praza@Sun.COM {
56517887SLiane.Praza@Sun.COM 	int i;
56527887SLiane.Praza@Sun.COM 
56537887SLiane.Praza@Sun.COM 	for (i = 0; i < ir->sir_num_ranges; ++i) {
56547887SLiane.Praza@Sun.COM 		if (v >= ir->sir_min[i] &&
56557887SLiane.Praza@Sun.COM 		    v <= ir->sir_max[i]) {
56567887SLiane.Praza@Sun.COM 			/* value is within integer ranges constraint */
56577887SLiane.Praza@Sun.COM 			return (0);
56587887SLiane.Praza@Sun.COM 		}
56597887SLiane.Praza@Sun.COM 	}
56607887SLiane.Praza@Sun.COM 	return (-1);
56617887SLiane.Praza@Sun.COM }
56627887SLiane.Praza@Sun.COM 
56637887SLiane.Praza@Sun.COM /*
56647887SLiane.Praza@Sun.COM  * int _value_in_constraint()
56657887SLiane.Praza@Sun.COM  *
56667887SLiane.Praza@Sun.COM  * Checks whether the supplied value violates any of the constraints
56677887SLiane.Praza@Sun.COM  * specified in the supplied property template.  If it does, an appropriate
56687887SLiane.Praza@Sun.COM  * error is appended to "errs".  pg and prop, if supplied, are used to
56697887SLiane.Praza@Sun.COM  * augment the information in the error.  Returns 0 on success.
56707887SLiane.Praza@Sun.COM  *
56717887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
56727887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
56737887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
56747887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
56757887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
56767887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
56777887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
56787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
56797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
56807887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
56817887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
56827887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
56837887SLiane.Praza@Sun.COM  */
56847887SLiane.Praza@Sun.COM static int
_value_in_constraint(scf_propertygroup_t * pg,scf_property_t * prop,const scf_prop_tmpl_t * pt,scf_value_t * value,scf_tmpl_errors_t * errs)56857887SLiane.Praza@Sun.COM _value_in_constraint(scf_propertygroup_t *pg, scf_property_t *prop,
56867887SLiane.Praza@Sun.COM     const scf_prop_tmpl_t *pt, scf_value_t *value, scf_tmpl_errors_t *errs)
56877887SLiane.Praza@Sun.COM {
56887887SLiane.Praza@Sun.COM 	scf_type_t type, tmpl_type;
56897887SLiane.Praza@Sun.COM 	scf_values_t vals;
56907887SLiane.Praza@Sun.COM 	scf_tmpl_error_type_t terr_type;
56917887SLiane.Praza@Sun.COM 	uint64_t v_count;
56927887SLiane.Praza@Sun.COM 	int64_t v_int;
56937887SLiane.Praza@Sun.COM 	char *vstr;
56947887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
56957887SLiane.Praza@Sun.COM 	ssize_t ret = 0;
56967887SLiane.Praza@Sun.COM 	char **constraints;
56977887SLiane.Praza@Sun.COM 	int n = 0;
56987887SLiane.Praza@Sun.COM 	int r;
56997887SLiane.Praza@Sun.COM 	int err_flag = 0;
57007887SLiane.Praza@Sun.COM 	scf_count_ranges_t cr;
57017887SLiane.Praza@Sun.COM 	scf_int_ranges_t ir;
57027887SLiane.Praza@Sun.COM 
57037887SLiane.Praza@Sun.COM 	type = scf_value_type(value);
57047887SLiane.Praza@Sun.COM 	if (type == SCF_TYPE_INVALID) {
57057887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
57067887SLiane.Praza@Sun.COM 		return (-1);
57077887SLiane.Praza@Sun.COM 	}
57087887SLiane.Praza@Sun.COM 
57097887SLiane.Praza@Sun.COM 	/* Check if template type matches value type. */
57107887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) {
57117887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND)
57127887SLiane.Praza@Sun.COM 			/* type is not wildcarded */
57137887SLiane.Praza@Sun.COM 			return (-1);
57147887SLiane.Praza@Sun.COM 	} else if (tmpl_type != type) {
57157887SLiane.Praza@Sun.COM 		if (errs != NULL) {
57167887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL) {
57177887SLiane.Praza@Sun.COM 				if (_add_tmpl_constraint_error(errs,
57187887SLiane.Praza@Sun.COM 				    SCF_TERR_PROP_TYPE_MISMATCH, NULL, pt,
57197887SLiane.Praza@Sun.COM 				    NULL, value) == -1)
57207887SLiane.Praza@Sun.COM 					return (-1);
57217887SLiane.Praza@Sun.COM 			}
57227887SLiane.Praza@Sun.COM 		}
57237887SLiane.Praza@Sun.COM 		return (1);
57247887SLiane.Praza@Sun.COM 	}
57257887SLiane.Praza@Sun.COM 
57267887SLiane.Praza@Sun.COM 	/* Numeric values should be checked against any range constraints. */
57277887SLiane.Praza@Sun.COM 	switch (type) {
57287887SLiane.Praza@Sun.COM 	case SCF_TYPE_COUNT:
57297887SLiane.Praza@Sun.COM 		r = scf_value_get_count(value, &v_count);
57307887SLiane.Praza@Sun.COM 		assert(r == 0);
57317887SLiane.Praza@Sun.COM 
57327887SLiane.Praza@Sun.COM 		if (scf_tmpl_value_count_range_constraints(pt, &cr) != 0) {
57337887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
57347887SLiane.Praza@Sun.COM 				break;
57357887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
57367887SLiane.Praza@Sun.COM 				(void) scf_set_error(
57377887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
57387887SLiane.Praza@Sun.COM 			return (-1);
57397887SLiane.Praza@Sun.COM 		} else {
57407887SLiane.Praza@Sun.COM 			if (_check_count_ranges(&cr, v_count) == 0) {
57417887SLiane.Praza@Sun.COM 				/* value is within ranges constraint */
57427887SLiane.Praza@Sun.COM 				scf_count_ranges_destroy(&cr);
57437887SLiane.Praza@Sun.COM 				return (0);
57447887SLiane.Praza@Sun.COM 			}
57457887SLiane.Praza@Sun.COM 			scf_count_ranges_destroy(&cr);
57467887SLiane.Praza@Sun.COM 		}
57477887SLiane.Praza@Sun.COM 
57487887SLiane.Praza@Sun.COM 		/*
57497887SLiane.Praza@Sun.COM 		 * If we get here, we have a possible constraint
57507887SLiane.Praza@Sun.COM 		 * violation.
57517887SLiane.Praza@Sun.COM 		 */
57527887SLiane.Praza@Sun.COM 		err_flag |= 0x1; /* RANGE_VIOLATION, count */
57537887SLiane.Praza@Sun.COM 		break;
57547887SLiane.Praza@Sun.COM 	case SCF_TYPE_INTEGER:
57557887SLiane.Praza@Sun.COM 		if (scf_value_get_integer(value, &v_int) != 0)
57567887SLiane.Praza@Sun.COM 			assert(0);
57577887SLiane.Praza@Sun.COM 		if (scf_tmpl_value_int_range_constraints(pt, &ir) != 0) {
57587887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
57597887SLiane.Praza@Sun.COM 				break;
57607887SLiane.Praza@Sun.COM 			if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED)
57617887SLiane.Praza@Sun.COM 				(void) scf_set_error(
57627887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
57637887SLiane.Praza@Sun.COM 			return (-1);
57647887SLiane.Praza@Sun.COM 		} else {
57657887SLiane.Praza@Sun.COM 			if (_check_int_ranges(&ir, v_int) == 0) {
57667887SLiane.Praza@Sun.COM 				/* value is within ranges constraint */
57677887SLiane.Praza@Sun.COM 				scf_int_ranges_destroy(&ir);
57687887SLiane.Praza@Sun.COM 				return (0);
57697887SLiane.Praza@Sun.COM 			}
57707887SLiane.Praza@Sun.COM 			scf_int_ranges_destroy(&ir);
57717887SLiane.Praza@Sun.COM 		}
57727887SLiane.Praza@Sun.COM 		/*
57737887SLiane.Praza@Sun.COM 		 * If we get here, we have a possible constraint
57747887SLiane.Praza@Sun.COM 		 * violation.
57757887SLiane.Praza@Sun.COM 		 */
57767887SLiane.Praza@Sun.COM 		err_flag |= 0x2; /* RANGE_VIOLATION, integer */
57777887SLiane.Praza@Sun.COM 		break;
57787887SLiane.Praza@Sun.COM 	default:
57797887SLiane.Praza@Sun.COM 		break;
57807887SLiane.Praza@Sun.COM 	}
57817887SLiane.Praza@Sun.COM 
57827887SLiane.Praza@Sun.COM 	vstr = malloc(sz);
57837887SLiane.Praza@Sun.COM 	if (vstr == NULL) {
57847887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
57857887SLiane.Praza@Sun.COM 		return (-1);
57867887SLiane.Praza@Sun.COM 	}
57877887SLiane.Praza@Sun.COM 
57887887SLiane.Praza@Sun.COM 	/*
57897887SLiane.Praza@Sun.COM 	 * If a set of names is provided, confirm value has one of
57907887SLiane.Praza@Sun.COM 	 * those names.
57917887SLiane.Praza@Sun.COM 	 */
57927887SLiane.Praza@Sun.COM 	if (scf_tmpl_value_name_constraints(pt, &vals) != 0) {
57937887SLiane.Praza@Sun.COM 		free(vstr);
57947887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
57957887SLiane.Praza@Sun.COM 			return (-1);
57967887SLiane.Praza@Sun.COM 		}
57977887SLiane.Praza@Sun.COM 	} else {
57987887SLiane.Praza@Sun.COM 		r = scf_value_get_as_string_typed(value, type, vstr, sz);
57997887SLiane.Praza@Sun.COM 
58007887SLiane.Praza@Sun.COM 		/*
58017887SLiane.Praza@Sun.COM 		 * All errors (INVALID_ARGUMENT, NOT_SET, TYPE_MISMATCH)
58027887SLiane.Praza@Sun.COM 		 * should be impossible or already caught above.
58037887SLiane.Praza@Sun.COM 		 */
58047887SLiane.Praza@Sun.COM 		assert(r > 0);
58057887SLiane.Praza@Sun.COM 
58067887SLiane.Praza@Sun.COM 		constraints = vals.values.v_astring;
58077887SLiane.Praza@Sun.COM 		for (n = 0; constraints[n] != NULL; ++n) {
58087887SLiane.Praza@Sun.COM 			if (strcmp(constraints[n], vstr) == 0) {
58097887SLiane.Praza@Sun.COM 				/* value is within constraint */
58107887SLiane.Praza@Sun.COM 				scf_values_destroy(&vals);
58117887SLiane.Praza@Sun.COM 				free(vstr);
58127887SLiane.Praza@Sun.COM 				return (0);
58137887SLiane.Praza@Sun.COM 			}
58147887SLiane.Praza@Sun.COM 		}
58157887SLiane.Praza@Sun.COM 		/* if we get here, we have a constraint violation */
58167887SLiane.Praza@Sun.COM 		err_flag |= 0x4; /* CONSTRAINT_VIOLATED */
58177887SLiane.Praza@Sun.COM 		scf_values_destroy(&vals);
58187887SLiane.Praza@Sun.COM 		free(vstr);
58197887SLiane.Praza@Sun.COM 	}
58207887SLiane.Praza@Sun.COM 	if (err_flag != 0)
58217887SLiane.Praza@Sun.COM 		ret = 1;
58227887SLiane.Praza@Sun.COM 	/* register the errors found */
58237887SLiane.Praza@Sun.COM 	if (ret == 1 && errs != NULL) {
58247887SLiane.Praza@Sun.COM 		if ((err_flag & 0x1) == 0x1) {
58257887SLiane.Praza@Sun.COM 			/*
58267887SLiane.Praza@Sun.COM 			 * Help make the error more human-friendly.  If
58277887SLiane.Praza@Sun.COM 			 * pg and prop are provided, we know we're
58287887SLiane.Praza@Sun.COM 			 * validating repository data.  If they're not,
58297887SLiane.Praza@Sun.COM 			 * we're validating a potentially hypothetical
58307887SLiane.Praza@Sun.COM 			 * value.
58317887SLiane.Praza@Sun.COM 			 */
58327887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL)
58337887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_VALUE_OUT_OF_RANGE;
58347887SLiane.Praza@Sun.COM 			else
58357887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_RANGE_VIOLATION;
58367887SLiane.Praza@Sun.COM 			if (_add_tmpl_count_error(errs, terr_type, pg, pt,
58377887SLiane.Praza@Sun.COM 			    prop, v_count, 0, 0) == -1)
58387887SLiane.Praza@Sun.COM 				ret = -1;
58397887SLiane.Praza@Sun.COM 		}
58407887SLiane.Praza@Sun.COM 		if ((err_flag & 0x2) == 0x2) {
58417887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL)
58427887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_VALUE_OUT_OF_RANGE;
58437887SLiane.Praza@Sun.COM 			else
58447887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_RANGE_VIOLATION;
58457887SLiane.Praza@Sun.COM 			if (_add_tmpl_int_error(errs, terr_type, pg, pt, prop,
58467887SLiane.Praza@Sun.COM 			    v_int, 0, 0) == -1)
58477887SLiane.Praza@Sun.COM 				ret = -1;
58487887SLiane.Praza@Sun.COM 		}
58497887SLiane.Praza@Sun.COM 		if ((err_flag & 0x4) == 0x4) {
58507887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL)
58517887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_INVALID_VALUE;
58527887SLiane.Praza@Sun.COM 			else
58537887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_VALUE_CONSTRAINT_VIOLATED;
58547887SLiane.Praza@Sun.COM 			if (_add_tmpl_constraint_error(errs, terr_type, pg,
58557887SLiane.Praza@Sun.COM 			    pt, prop, value) == -1)
58567887SLiane.Praza@Sun.COM 				ret = -1;
58577887SLiane.Praza@Sun.COM 		}
58587887SLiane.Praza@Sun.COM 	}
58597887SLiane.Praza@Sun.COM 	return (ret);
58607887SLiane.Praza@Sun.COM }
58617887SLiane.Praza@Sun.COM 
58627887SLiane.Praza@Sun.COM /*
58637887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
58647887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
58657887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
58667887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
58677887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
58687887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
58697887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
58707887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
58717887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
58727887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
58737887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
58747887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
58757887SLiane.Praza@Sun.COM  */
58767887SLiane.Praza@Sun.COM int
scf_tmpl_value_in_constraint(const scf_prop_tmpl_t * pt,scf_value_t * value,scf_tmpl_errors_t ** errs)58777887SLiane.Praza@Sun.COM scf_tmpl_value_in_constraint(const scf_prop_tmpl_t *pt, scf_value_t *value,
58787887SLiane.Praza@Sun.COM     scf_tmpl_errors_t **errs)
58797887SLiane.Praza@Sun.COM {
58807887SLiane.Praza@Sun.COM 	scf_tmpl_errors_t *e = NULL;
58817887SLiane.Praza@Sun.COM 
58827887SLiane.Praza@Sun.COM 	if (errs != NULL) {
58837887SLiane.Praza@Sun.COM 		char *fmri;
58847887SLiane.Praza@Sun.COM 
58857887SLiane.Praza@Sun.COM 		if ((fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
58867887SLiane.Praza@Sun.COM 			return (-1);
58877887SLiane.Praza@Sun.COM 		*errs = _scf_create_errors(fmri, 1);
58887887SLiane.Praza@Sun.COM 		free(fmri);
58897887SLiane.Praza@Sun.COM 		if (*errs == NULL)
58907887SLiane.Praza@Sun.COM 			return (-1);
58917887SLiane.Praza@Sun.COM 		e = *errs;
58927887SLiane.Praza@Sun.COM 	}
58937887SLiane.Praza@Sun.COM 
58947887SLiane.Praza@Sun.COM 	return (_value_in_constraint(NULL, NULL, pt, value, e));
58957887SLiane.Praza@Sun.COM }
58967887SLiane.Praza@Sun.COM 
58977887SLiane.Praza@Sun.COM scf_tmpl_error_t *
scf_tmpl_next_error(scf_tmpl_errors_t * errs)58987887SLiane.Praza@Sun.COM scf_tmpl_next_error(scf_tmpl_errors_t *errs)
58997887SLiane.Praza@Sun.COM {
59007887SLiane.Praza@Sun.COM 	if (errs->tes_index < errs->tes_num_errs) {
59017887SLiane.Praza@Sun.COM 		assert(errs->tes_errs[errs->tes_index] != NULL);
59027887SLiane.Praza@Sun.COM 		return (errs->tes_errs[errs->tes_index++]);
59037887SLiane.Praza@Sun.COM 	} else {
59047887SLiane.Praza@Sun.COM 		return (NULL);
59057887SLiane.Praza@Sun.COM 	}
59067887SLiane.Praza@Sun.COM }
59077887SLiane.Praza@Sun.COM 
59087887SLiane.Praza@Sun.COM void
scf_tmpl_reset_errors(scf_tmpl_errors_t * errs)59097887SLiane.Praza@Sun.COM scf_tmpl_reset_errors(scf_tmpl_errors_t *errs)
59107887SLiane.Praza@Sun.COM {
59117887SLiane.Praza@Sun.COM 	errs->tes_index = 0;
59127887SLiane.Praza@Sun.COM }
59137887SLiane.Praza@Sun.COM 
59147887SLiane.Praza@Sun.COM int
scf_tmpl_strerror(scf_tmpl_error_t * err,char * s,size_t n,int flag)59157887SLiane.Praza@Sun.COM scf_tmpl_strerror(scf_tmpl_error_t *err,  char *s, size_t n, int flag)
59167887SLiane.Praza@Sun.COM {
59177887SLiane.Praza@Sun.COM 	const char *str;
59187887SLiane.Praza@Sun.COM 	int i;
59197887SLiane.Praza@Sun.COM 	int ret = -1;
59207887SLiane.Praza@Sun.COM 	int nsz = 0;	/* err msg length */
59217887SLiane.Praza@Sun.COM 	int sz = n;	/* available buffer size */
59227887SLiane.Praza@Sun.COM 	char *buf = s;	/* where to append in buffer */
59237887SLiane.Praza@Sun.COM 	char *s0 = (flag == SCF_TMPL_STRERROR_HUMAN) ? ":\n\t" : ": ";
59247887SLiane.Praza@Sun.COM 	char *s1 = (flag == SCF_TMPL_STRERROR_HUMAN) ? "\n\t" : "; ";
59257887SLiane.Praza@Sun.COM 	char *sep = s0;
59267887SLiane.Praza@Sun.COM 	const char *val;
59277887SLiane.Praza@Sun.COM 
59287887SLiane.Praza@Sun.COM 	/* prefix */
59297887SLiane.Praza@Sun.COM 	if (err->te_errs->tes_prefix != NULL) {
59307887SLiane.Praza@Sun.COM 		ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN,
59317887SLiane.Praza@Sun.COM 		    err->te_errs->tes_prefix));
59327887SLiane.Praza@Sun.COM 		nsz += ret;
59337887SLiane.Praza@Sun.COM 		sz = (sz - ret) > 0 ? sz - ret : 0;
59347887SLiane.Praza@Sun.COM 		buf = (sz > 0) ? s + nsz : NULL;
59357887SLiane.Praza@Sun.COM 	}
59367887SLiane.Praza@Sun.COM 	/* error message */
59377887SLiane.Praza@Sun.COM 	ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN,
59387887SLiane.Praza@Sun.COM 	    em_desc[err->te_type].em_msg));
59397887SLiane.Praza@Sun.COM 	nsz += ret;
59407887SLiane.Praza@Sun.COM 	sz = (sz - ret) > 0 ? sz - ret : 0;
59417887SLiane.Praza@Sun.COM 	buf = (sz > 0) ? s + nsz : NULL;
59427887SLiane.Praza@Sun.COM 
59437887SLiane.Praza@Sun.COM 	for (i = 0; _tmpl_error_items[i].get_desc != NULL; ++i) {
59447887SLiane.Praza@Sun.COM 		if ((str = _tmpl_error_items[i].get_desc(err)) == NULL)
59457887SLiane.Praza@Sun.COM 			/* no item to print */
59467887SLiane.Praza@Sun.COM 			continue;
59477887SLiane.Praza@Sun.COM 		val = _tmpl_error_items[i].get_val(err);
59487887SLiane.Praza@Sun.COM 		ret = snprintf(buf, sz, "%s%s=\"%s\"", sep, str,
59497887SLiane.Praza@Sun.COM 		    (val == NULL) ? "" : val);
59507887SLiane.Praza@Sun.COM 		nsz += ret;
59517887SLiane.Praza@Sun.COM 		sz = (sz - ret) > 0 ? sz - ret : 0;
59527887SLiane.Praza@Sun.COM 		buf = (sz > 0) ? s + nsz : NULL;
59537887SLiane.Praza@Sun.COM 		sep = s1;
59547887SLiane.Praza@Sun.COM 	}
59557887SLiane.Praza@Sun.COM 	return (nsz);
59567887SLiane.Praza@Sun.COM }
59577887SLiane.Praza@Sun.COM 
59587887SLiane.Praza@Sun.COM /*
59597887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
59607887SLiane.Praza@Sun.COM  * set scf_error() to:
59617887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
59627887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
59637887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
59647887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
59657887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
59667887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
59677887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
59687887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
59697887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
59707887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
59717887SLiane.Praza@Sun.COM  */
59727887SLiane.Praza@Sun.COM static int
_validate_cardinality(scf_propertygroup_t * pg,scf_prop_tmpl_t * pt,scf_property_t * prop,scf_tmpl_errors_t * errs)59737887SLiane.Praza@Sun.COM _validate_cardinality(scf_propertygroup_t *pg, scf_prop_tmpl_t *pt,
59747887SLiane.Praza@Sun.COM     scf_property_t *prop, scf_tmpl_errors_t *errs)
59757887SLiane.Praza@Sun.COM {
59767887SLiane.Praza@Sun.COM 	uint64_t min, max;
59777887SLiane.Praza@Sun.COM 	scf_handle_t *h;
59787887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
59797887SLiane.Praza@Sun.COM 	scf_value_t *val = NULL;
59807887SLiane.Praza@Sun.COM 	int count = 0;
59817887SLiane.Praza@Sun.COM 	int ret = -1;
59827887SLiane.Praza@Sun.COM 	int r;
59837887SLiane.Praza@Sun.COM 
59847887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_cardinality(pt, &min, &max) != 0) {
59857887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND)
59867887SLiane.Praza@Sun.COM 			return (0);
59877887SLiane.Praza@Sun.COM 		else
59887887SLiane.Praza@Sun.COM 			return (-1);
59897887SLiane.Praza@Sun.COM 	}
59907887SLiane.Praza@Sun.COM 
59917887SLiane.Praza@Sun.COM 	/* Any number of values permitted.  Just return success. */
59927887SLiane.Praza@Sun.COM 	if (min == 0 && max == UINT64_MAX) {
59937887SLiane.Praza@Sun.COM 		return (0);
59947887SLiane.Praza@Sun.COM 	}
59957887SLiane.Praza@Sun.COM 
59967887SLiane.Praza@Sun.COM 	h = scf_property_handle(prop);
59977887SLiane.Praza@Sun.COM 	if (h == NULL) {
59987887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
59997887SLiane.Praza@Sun.COM 		goto cleanup;
60007887SLiane.Praza@Sun.COM 	}
60017887SLiane.Praza@Sun.COM 
60027887SLiane.Praza@Sun.COM 	iter = scf_iter_create(h);
60037887SLiane.Praza@Sun.COM 	val = scf_value_create(h);
60047887SLiane.Praza@Sun.COM 	if (iter == NULL || val == NULL) {
60057887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
60067887SLiane.Praza@Sun.COM 			goto cleanup;
60077887SLiane.Praza@Sun.COM 		} else {
60087887SLiane.Praza@Sun.COM 			assert(0);
60097887SLiane.Praza@Sun.COM 			abort();
60107887SLiane.Praza@Sun.COM 		}
60117887SLiane.Praza@Sun.COM 	}
60127887SLiane.Praza@Sun.COM 
60137887SLiane.Praza@Sun.COM 	if (scf_iter_property_values(iter, prop) != 0) {
60147887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
60157887SLiane.Praza@Sun.COM 			goto cleanup;
60167887SLiane.Praza@Sun.COM 		} else {
60177887SLiane.Praza@Sun.COM 			assert(0);
60187887SLiane.Praza@Sun.COM 			abort();
60197887SLiane.Praza@Sun.COM 		}
60207887SLiane.Praza@Sun.COM 	}
60217887SLiane.Praza@Sun.COM 
60227887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_value(iter, val)) == 1)
60237887SLiane.Praza@Sun.COM 		count++;
60247887SLiane.Praza@Sun.COM 
60257887SLiane.Praza@Sun.COM 	if (r < 0) {
60267887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
60277887SLiane.Praza@Sun.COM 			goto cleanup;
60287887SLiane.Praza@Sun.COM 		} else {
60297887SLiane.Praza@Sun.COM 			assert(0);
60307887SLiane.Praza@Sun.COM 			abort();
60317887SLiane.Praza@Sun.COM 		}
60327887SLiane.Praza@Sun.COM 	}
60337887SLiane.Praza@Sun.COM 
60347887SLiane.Praza@Sun.COM 	if (count < min || count > max)
60357887SLiane.Praza@Sun.COM 		if (_add_tmpl_count_error(errs, SCF_TERR_CARDINALITY_VIOLATION,
60367887SLiane.Praza@Sun.COM 		    pg, pt, prop, (uint64_t)count, &min, &max) == -1)
60377887SLiane.Praza@Sun.COM 			goto cleanup;
60387887SLiane.Praza@Sun.COM 
60397887SLiane.Praza@Sun.COM 	ret = 0;
60407887SLiane.Praza@Sun.COM 
60417887SLiane.Praza@Sun.COM cleanup:
60427887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
60437887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
60447887SLiane.Praza@Sun.COM 	return (ret);
60457887SLiane.Praza@Sun.COM }
60467887SLiane.Praza@Sun.COM 
60477887SLiane.Praza@Sun.COM /*
60487887SLiane.Praza@Sun.COM  * Returns -1 on error.  Sets scf_error():
60497887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
60507887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
60517887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
60527887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
60537887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
60547887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
60557887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
60567887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
60577887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
60587887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
60597887SLiane.Praza@Sun.COM  */
60607887SLiane.Praza@Sun.COM static int
_check_property(scf_prop_tmpl_t * pt,scf_propertygroup_t * pg,scf_property_t * prop,scf_tmpl_errors_t * errs)60617887SLiane.Praza@Sun.COM _check_property(scf_prop_tmpl_t *pt, scf_propertygroup_t *pg,
60627887SLiane.Praza@Sun.COM     scf_property_t *prop, scf_tmpl_errors_t *errs)
60637887SLiane.Praza@Sun.COM {
60647887SLiane.Praza@Sun.COM 	scf_type_t tmpl_type;
60657887SLiane.Praza@Sun.COM 	uint8_t required;
60667887SLiane.Praza@Sun.COM 	scf_handle_t *h;
60677887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
60687887SLiane.Praza@Sun.COM 	scf_value_t *val = NULL;
60697887SLiane.Praza@Sun.COM 	int r;
60707887SLiane.Praza@Sun.COM 	int ret = -1;
60717887SLiane.Praza@Sun.COM 
60727887SLiane.Praza@Sun.COM 	h = scf_pg_handle(pg);
60737887SLiane.Praza@Sun.COM 	if (h == NULL) {
60747887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
60757887SLiane.Praza@Sun.COM 		return (-1);
60767887SLiane.Praza@Sun.COM 	}
60777887SLiane.Praza@Sun.COM 
60787887SLiane.Praza@Sun.COM 	iter = scf_iter_create(h);
60797887SLiane.Praza@Sun.COM 	val = scf_value_create(h);
60807887SLiane.Praza@Sun.COM 	if (iter == NULL || val == NULL) {
60817887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
60827887SLiane.Praza@Sun.COM 			scf_iter_destroy(iter);
60837887SLiane.Praza@Sun.COM 			scf_value_destroy(val);
60847887SLiane.Praza@Sun.COM 			return (-1);
60857887SLiane.Praza@Sun.COM 		} else {
60867887SLiane.Praza@Sun.COM 			assert(0);
60877887SLiane.Praza@Sun.COM 			abort();
60887887SLiane.Praza@Sun.COM 		}
60897887SLiane.Praza@Sun.COM 	}
60907887SLiane.Praza@Sun.COM 
60917887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_required(pt, &required) != 0)
60927887SLiane.Praza@Sun.COM 		goto cleanup;
60937887SLiane.Praza@Sun.COM 
60947887SLiane.Praza@Sun.COM 	/* Check type */
60957887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) {
60967887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
60977887SLiane.Praza@Sun.COM 			goto cleanup;
60987887SLiane.Praza@Sun.COM 		} else if (required) {
60997887SLiane.Praza@Sun.COM 			/* If required, type must be specified. */
61007887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
61017887SLiane.Praza@Sun.COM 			goto cleanup;
61027887SLiane.Praza@Sun.COM 		}
61037887SLiane.Praza@Sun.COM 	} else if (scf_property_is_type(prop, tmpl_type) != 0) {
61047887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
61057887SLiane.Praza@Sun.COM 			goto cleanup;
61067887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
61077887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
61087887SLiane.Praza@Sun.COM 			if (_add_tmpl_wrong_prop_type_error(errs, pg, pt,
61097887SLiane.Praza@Sun.COM 			    prop) == -1)
61107887SLiane.Praza@Sun.COM 				goto cleanup;
61117887SLiane.Praza@Sun.COM 			break;
61127887SLiane.Praza@Sun.COM 
61137887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
61147887SLiane.Praza@Sun.COM 			/*
61157887SLiane.Praza@Sun.COM 			 * tmpl_prop_type shouldn't have handed back
61167887SLiane.Praza@Sun.COM 			 * an invalid property type.
61177887SLiane.Praza@Sun.COM 			 */
61187887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
61197887SLiane.Praza@Sun.COM 		default:
61207887SLiane.Praza@Sun.COM 			assert(0);
61217887SLiane.Praza@Sun.COM 			abort();
61227887SLiane.Praza@Sun.COM 		}
61237887SLiane.Praza@Sun.COM 	}
61247887SLiane.Praza@Sun.COM 
61257887SLiane.Praza@Sun.COM 
61267887SLiane.Praza@Sun.COM 	/* Cardinality */
61277887SLiane.Praza@Sun.COM 	if (_validate_cardinality(pg, pt, prop, errs) == -1)
61287887SLiane.Praza@Sun.COM 		goto cleanup;
61297887SLiane.Praza@Sun.COM 
61307887SLiane.Praza@Sun.COM 	/* Value constraints */
61317887SLiane.Praza@Sun.COM 	/*
61327887SLiane.Praza@Sun.COM 	 * Iterate through each value, and confirm it is defined as
61337887SLiane.Praza@Sun.COM 	 * constrained.
61347887SLiane.Praza@Sun.COM 	 */
61357887SLiane.Praza@Sun.COM 	if (scf_iter_property_values(iter, prop) != 0) {
61367887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET &&
61377887SLiane.Praza@Sun.COM 		    scf_error() != SCF_ERROR_HANDLE_MISMATCH);
61387887SLiane.Praza@Sun.COM 		goto cleanup;
61397887SLiane.Praza@Sun.COM 	}
61407887SLiane.Praza@Sun.COM 
61417887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_value(iter, val)) == 1) {
61427887SLiane.Praza@Sun.COM 		if (_value_in_constraint(pg, prop, pt, val, errs) == -1) {
61437887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
61447887SLiane.Praza@Sun.COM 				goto cleanup;
61457887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
61467887SLiane.Praza@Sun.COM 			case SCF_ERROR_TEMPLATE_INVALID:
61477887SLiane.Praza@Sun.COM 				goto cleanup;
61487887SLiane.Praza@Sun.COM 
61497887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
61507887SLiane.Praza@Sun.COM 			default:
61517887SLiane.Praza@Sun.COM 				assert(0);
61527887SLiane.Praza@Sun.COM 				abort();
61537887SLiane.Praza@Sun.COM 			}
61547887SLiane.Praza@Sun.COM 		}
61557887SLiane.Praza@Sun.COM 	}
61567887SLiane.Praza@Sun.COM 
61577887SLiane.Praza@Sun.COM 	if (r < 0) {
61587887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
61597887SLiane.Praza@Sun.COM 			goto cleanup;
61607887SLiane.Praza@Sun.COM 		} else {
61617887SLiane.Praza@Sun.COM 			assert(0);
61627887SLiane.Praza@Sun.COM 			abort();
61637887SLiane.Praza@Sun.COM 		}
61647887SLiane.Praza@Sun.COM 	}
61657887SLiane.Praza@Sun.COM 
61667887SLiane.Praza@Sun.COM 	ret = 0;
61677887SLiane.Praza@Sun.COM 
61687887SLiane.Praza@Sun.COM cleanup:
61697887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
61707887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
61717887SLiane.Praza@Sun.COM 	return (ret);
61727887SLiane.Praza@Sun.COM }
61737887SLiane.Praza@Sun.COM 
61747887SLiane.Praza@Sun.COM /*
61757887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
61767887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
61777887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
61787887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
61797887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
61807887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
61817887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
61827887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
61837887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
61847887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
61857887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
61867887SLiane.Praza@Sun.COM  */
61877887SLiane.Praza@Sun.COM static int
_check_pg(scf_pg_tmpl_t * t,scf_propertygroup_t * pg,char * pg_name,char * type,scf_tmpl_errors_t * errs)61887887SLiane.Praza@Sun.COM _check_pg(scf_pg_tmpl_t *t, scf_propertygroup_t *pg, char *pg_name,
61897887SLiane.Praza@Sun.COM     char *type, scf_tmpl_errors_t *errs)
61907887SLiane.Praza@Sun.COM {
61917887SLiane.Praza@Sun.COM 	scf_prop_tmpl_t *pt = NULL;
61927887SLiane.Praza@Sun.COM 	char *pg_type = NULL;
61937887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
61947887SLiane.Praza@Sun.COM 	uint8_t pg_required;
61957887SLiane.Praza@Sun.COM 	scf_property_t *prop = NULL;
61967887SLiane.Praza@Sun.COM 	scf_handle_t *h;
61977887SLiane.Praza@Sun.COM 	int r;
61987887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
61997887SLiane.Praza@Sun.COM 	ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
62007887SLiane.Praza@Sun.COM 	int ret = -1;
62017887SLiane.Praza@Sun.COM 
62027887SLiane.Praza@Sun.COM 	assert(pg_name != NULL);
62037887SLiane.Praza@Sun.COM 	assert(t != NULL);
62047887SLiane.Praza@Sun.COM 	assert(pg != NULL);
62057887SLiane.Praza@Sun.COM 	assert(type != NULL);
62067887SLiane.Praza@Sun.COM 	assert(nsize != 0);
62077887SLiane.Praza@Sun.COM 
62087887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
62097887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
62107887SLiane.Praza@Sun.COM 		return (-1);
62117887SLiane.Praza@Sun.COM 	}
62127887SLiane.Praza@Sun.COM 	if ((pt = scf_tmpl_prop_create(h)) == NULL) {
62137887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
62147887SLiane.Praza@Sun.COM 		return (-1);
62157887SLiane.Praza@Sun.COM 	}
62167887SLiane.Praza@Sun.COM 
62177887SLiane.Praza@Sun.COM 	if ((prop = scf_property_create(h)) == NULL) {
62187887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
62197887SLiane.Praza@Sun.COM 		goto cleanup;
62207887SLiane.Praza@Sun.COM 	}
62217887SLiane.Praza@Sun.COM 
62227887SLiane.Praza@Sun.COM 	if ((iter = scf_iter_create(h)) == NULL) {
62237887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
62247887SLiane.Praza@Sun.COM 		goto cleanup;
62257887SLiane.Praza@Sun.COM 	}
62267887SLiane.Praza@Sun.COM 	if ((prop_name = malloc(nsize)) == NULL) {
62277887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
62287887SLiane.Praza@Sun.COM 		goto cleanup;
62297887SLiane.Praza@Sun.COM 	}
62307887SLiane.Praza@Sun.COM 
62317887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_required(t, &pg_required) != 0)
62327887SLiane.Praza@Sun.COM 		goto cleanup;
62337887SLiane.Praza@Sun.COM 
62347887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &pg_type) == -1) {
62357887SLiane.Praza@Sun.COM 		goto cleanup;
62367887SLiane.Praza@Sun.COM 	} else if (pg_required != 0 &&
62377887SLiane.Praza@Sun.COM 	    strcmp(SCF_TMPL_WILDCARD, pg_type) == 0) {
62387887SLiane.Praza@Sun.COM 		/* Type must be specified for required pgs. */
62397887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
62407887SLiane.Praza@Sun.COM 		goto cleanup;
62417887SLiane.Praza@Sun.COM 	}
62427887SLiane.Praza@Sun.COM 
62437887SLiane.Praza@Sun.COM 	if (pg_type != NULL) {
62447887SLiane.Praza@Sun.COM 		if (strcmp(pg_type, type) != 0 &&
62457887SLiane.Praza@Sun.COM 		    strcmp(pg_type, SCF_TMPL_WILDCARD) != 0) {
62467887SLiane.Praza@Sun.COM 			if (_add_tmpl_wrong_pg_type_error(errs, t, pg) == -1)
62477887SLiane.Praza@Sun.COM 				goto cleanup;
62487887SLiane.Praza@Sun.COM 		}
62497887SLiane.Praza@Sun.COM 	}
62507887SLiane.Praza@Sun.COM 
62517887SLiane.Praza@Sun.COM 
62527887SLiane.Praza@Sun.COM 	/* Iterate through properties in the repository and check them. */
62537887SLiane.Praza@Sun.COM 	if (scf_iter_pg_properties(iter, pg) != 0) {
62547887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
62557887SLiane.Praza@Sun.COM 			goto cleanup;
62567887SLiane.Praza@Sun.COM 		} else {
62577887SLiane.Praza@Sun.COM 			assert(0);
62587887SLiane.Praza@Sun.COM 			abort();
62597887SLiane.Praza@Sun.COM 		}
62607887SLiane.Praza@Sun.COM 	}
62617887SLiane.Praza@Sun.COM 
62627887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_property(iter, prop)) == 1) {
62637887SLiane.Praza@Sun.COM 		if (scf_property_get_name(prop, prop_name, nsize) == -1) {
62647887SLiane.Praza@Sun.COM 			assert(scf_error() != SCF_ERROR_NOT_SET);
62657887SLiane.Praza@Sun.COM 			goto cleanup;
62667887SLiane.Praza@Sun.COM 		}
62677887SLiane.Praza@Sun.COM 		if (scf_tmpl_get_by_prop(t, prop_name, pt, 0) != 0) {
62687887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
62697887SLiane.Praza@Sun.COM 				goto cleanup;
62707887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
62717887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
62727887SLiane.Praza@Sun.COM 				/* No template.  Continue. */
62737887SLiane.Praza@Sun.COM 				continue;
62747887SLiane.Praza@Sun.COM 
62757887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
62767887SLiane.Praza@Sun.COM 			default:
62777887SLiane.Praza@Sun.COM 				assert(0);
62787887SLiane.Praza@Sun.COM 				abort();
62797887SLiane.Praza@Sun.COM 			}
62807887SLiane.Praza@Sun.COM 		}
62817887SLiane.Praza@Sun.COM 
62827887SLiane.Praza@Sun.COM 		if (_check_property(pt, pg, prop, errs) != 0)
62837887SLiane.Praza@Sun.COM 			goto cleanup;
62847887SLiane.Praza@Sun.COM 	}
62857887SLiane.Praza@Sun.COM 
62867887SLiane.Praza@Sun.COM 	if (r < 0) {
62877887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
62887887SLiane.Praza@Sun.COM 			goto cleanup;
62897887SLiane.Praza@Sun.COM 		} else {
62907887SLiane.Praza@Sun.COM 			assert(0);
62917887SLiane.Praza@Sun.COM 			abort();
62927887SLiane.Praza@Sun.COM 		}
62937887SLiane.Praza@Sun.COM 	}
62947887SLiane.Praza@Sun.COM 
62957887SLiane.Praza@Sun.COM 	scf_tmpl_prop_reset(pt);
62967887SLiane.Praza@Sun.COM 	free(prop_name);
62977887SLiane.Praza@Sun.COM 	prop_name = NULL;
62987887SLiane.Praza@Sun.COM 	/*
62997887SLiane.Praza@Sun.COM 	 * Confirm required properties are present.
63007887SLiane.Praza@Sun.COM 	 */
63017887SLiane.Praza@Sun.COM 	while ((r = scf_tmpl_iter_props(t, pt,
63027887SLiane.Praza@Sun.COM 	    SCF_PROP_TMPL_FLAG_REQUIRED)) == 0) {
63037887SLiane.Praza@Sun.COM 		scf_type_t prop_type;
63047887SLiane.Praza@Sun.COM 
63057887SLiane.Praza@Sun.COM 		if (scf_tmpl_prop_name(pt, &prop_name) == -1)
63067887SLiane.Praza@Sun.COM 			goto cleanup;
63077887SLiane.Praza@Sun.COM 
63087887SLiane.Praza@Sun.COM 		/* required properties cannot have type wildcarded */
63097887SLiane.Praza@Sun.COM 		if (scf_tmpl_prop_type(pt, &prop_type) == -1) {
63107887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
63117887SLiane.Praza@Sun.COM 				(void) scf_set_error(
63127887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
63137887SLiane.Praza@Sun.COM 			goto cleanup;
63147887SLiane.Praza@Sun.COM 		}
63157887SLiane.Praza@Sun.COM 
63167887SLiane.Praza@Sun.COM 		if (scf_pg_get_property(pg, prop_name, prop) != 0) {
63177887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
63187887SLiane.Praza@Sun.COM 				goto cleanup;
63197887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
63207887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
63217887SLiane.Praza@Sun.COM 				if (_add_tmpl_missing_prop_error(errs, t, pg,
63227887SLiane.Praza@Sun.COM 				    pt) == -1)
63237887SLiane.Praza@Sun.COM 					goto cleanup;
63247887SLiane.Praza@Sun.COM 				break;
63257887SLiane.Praza@Sun.COM 
63267887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
63277887SLiane.Praza@Sun.COM 				(void) scf_set_error(
63287887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
63297887SLiane.Praza@Sun.COM 				goto cleanup;
63307887SLiane.Praza@Sun.COM 
63317887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
63327887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
63337887SLiane.Praza@Sun.COM 			default:
63347887SLiane.Praza@Sun.COM 				assert(0);
63357887SLiane.Praza@Sun.COM 				abort();
63367887SLiane.Praza@Sun.COM 			}
63377887SLiane.Praza@Sun.COM 		}
63387887SLiane.Praza@Sun.COM 		free(prop_name);
63397887SLiane.Praza@Sun.COM 		prop_name = NULL;
63407887SLiane.Praza@Sun.COM 	}
63417887SLiane.Praza@Sun.COM 	if (r < 0) {
63427887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
63437887SLiane.Praza@Sun.COM 			goto cleanup;
63447887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
63457887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
63467887SLiane.Praza@Sun.COM 			break;
63477887SLiane.Praza@Sun.COM 
63487887SLiane.Praza@Sun.COM 		case SCF_ERROR_TEMPLATE_INVALID:
63497887SLiane.Praza@Sun.COM 			goto cleanup;
63507887SLiane.Praza@Sun.COM 
63517887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
63527887SLiane.Praza@Sun.COM 		default:
63537887SLiane.Praza@Sun.COM 			assert(0);
63547887SLiane.Praza@Sun.COM 			abort();
63557887SLiane.Praza@Sun.COM 		}
63567887SLiane.Praza@Sun.COM 	}
63577887SLiane.Praza@Sun.COM 
63587887SLiane.Praza@Sun.COM 	ret = 0;
63597887SLiane.Praza@Sun.COM cleanup:
63607887SLiane.Praza@Sun.COM 	scf_tmpl_prop_destroy(pt);
63617887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
63627887SLiane.Praza@Sun.COM 	scf_property_destroy(prop);
63637887SLiane.Praza@Sun.COM 	free(prop_name);
63647887SLiane.Praza@Sun.COM 	free(pg_type);
63657887SLiane.Praza@Sun.COM 	return (ret);
63667887SLiane.Praza@Sun.COM }
63677887SLiane.Praza@Sun.COM 
63687887SLiane.Praza@Sun.COM /*
63697887SLiane.Praza@Sun.COM  * Checks if instance fmri redefines any pgs defined in restarter or global
63707887SLiane.Praza@Sun.COM  * Return -1 on failure, sets scf_error() to:
63717887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
63727887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
63737887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
63747887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
63757887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
63767887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
63777887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
63787887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
63797887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
63807887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
63817887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
63827887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
63837887SLiane.Praza@Sun.COM  */
63847887SLiane.Praza@Sun.COM static int
_scf_tmpl_check_pg_redef(scf_handle_t * h,const char * fmri,const char * snapname,scf_tmpl_errors_t * errs)63857887SLiane.Praza@Sun.COM _scf_tmpl_check_pg_redef(scf_handle_t *h, const char *fmri,
63867887SLiane.Praza@Sun.COM     const char *snapname, scf_tmpl_errors_t *errs)
63877887SLiane.Praza@Sun.COM {
63887887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *t = NULL;
63897887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *r = NULL;
63907887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
63917887SLiane.Praza@Sun.COM 	char *pg_name_r = NULL;
63927887SLiane.Praza@Sun.COM 	char *pg_type = NULL;
63937887SLiane.Praza@Sun.COM 	char *pg_type_r = NULL;
63947887SLiane.Praza@Sun.COM 	char *target = NULL;
63957887SLiane.Praza@Sun.COM 	int ret_val = -1;
63967887SLiane.Praza@Sun.COM 	int ret;
63977887SLiane.Praza@Sun.COM 
63987887SLiane.Praza@Sun.COM 	t = scf_tmpl_pg_create(h);
63997887SLiane.Praza@Sun.COM 	r = scf_tmpl_pg_create(h);
64007887SLiane.Praza@Sun.COM 	if (t == NULL || r == NULL)
64017887SLiane.Praza@Sun.COM 		goto cleanup;
64027887SLiane.Praza@Sun.COM 
64037887SLiane.Praza@Sun.COM 	while ((ret = scf_tmpl_iter_pgs(t, fmri, snapname, NULL,
64047887SLiane.Praza@Sun.COM 	    SCF_PG_TMPL_FLAG_EXACT)) == 1) {
64057887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_name(t, &pg_name) == -1) {
64067887SLiane.Praza@Sun.COM 			goto cleanup;
64077887SLiane.Praza@Sun.COM 		}
64087887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_type(t, &pg_type) == -1) {
64097887SLiane.Praza@Sun.COM 			goto cleanup;
64107887SLiane.Praza@Sun.COM 		}
64117887SLiane.Praza@Sun.COM 		/* look for a redefinition of a global/restarter pg_pattern */
64127887SLiane.Praza@Sun.COM 		while ((ret = scf_tmpl_iter_pgs(r, fmri, snapname, pg_type,
64137887SLiane.Praza@Sun.COM 		    0)) == 1) {
64147887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_name(r, &pg_name_r) == -1) {
64157887SLiane.Praza@Sun.COM 				goto cleanup;
64167887SLiane.Praza@Sun.COM 			} else if (strcmp(pg_name_r, SCF_TMPL_WILDCARD) != 0 &&
64177887SLiane.Praza@Sun.COM 			    strcmp(pg_name, SCF_TMPL_WILDCARD) != 0 &&
64187887SLiane.Praza@Sun.COM 			    strcmp(pg_name, pg_name_r) != 0) {
64197887SLiane.Praza@Sun.COM 				/* not a match */
64207887SLiane.Praza@Sun.COM 				free(pg_name_r);
64217887SLiane.Praza@Sun.COM 				pg_name_r = NULL;
64227887SLiane.Praza@Sun.COM 				continue;
64237887SLiane.Praza@Sun.COM 			}
64247887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_type(r, &pg_type_r) == -1) {
64257887SLiane.Praza@Sun.COM 				goto cleanup;
64267887SLiane.Praza@Sun.COM 			} else if (strcmp(pg_type_r, SCF_TMPL_WILDCARD) != 0 &&
64277887SLiane.Praza@Sun.COM 			    strcmp(pg_type, SCF_TMPL_WILDCARD) != 0 &&
64287887SLiane.Praza@Sun.COM 			    strcmp(pg_type, pg_type_r) != 0) {
64297887SLiane.Praza@Sun.COM 				/* not a match */
64307887SLiane.Praza@Sun.COM 				free(pg_name_r);
64317887SLiane.Praza@Sun.COM 				pg_name_r = NULL;
64327887SLiane.Praza@Sun.COM 				free(pg_type_r);
64337887SLiane.Praza@Sun.COM 				pg_type_r = NULL;
64347887SLiane.Praza@Sun.COM 				continue;
64357887SLiane.Praza@Sun.COM 			}
64367887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_target(r, &target) == -1) {
64377887SLiane.Praza@Sun.COM 				target = NULL;
64387887SLiane.Praza@Sun.COM 				goto cleanup;
64397887SLiane.Praza@Sun.COM 			}
64407887SLiane.Praza@Sun.COM 			if (strcmp(target, SCF_TM_TARGET_ALL) == 0 ||
64417887SLiane.Praza@Sun.COM 			    strcmp(target, SCF_TM_TARGET_DELEGATE) == 0) {
64427887SLiane.Praza@Sun.COM 				/* found a pg_pattern redefinition */
64437887SLiane.Praza@Sun.COM 				if (_add_tmpl_pg_redefine_error(errs, t,
64447887SLiane.Praza@Sun.COM 				    r) == -1)
64457887SLiane.Praza@Sun.COM 					goto cleanup;
64467887SLiane.Praza@Sun.COM 				free(pg_name_r);
64477887SLiane.Praza@Sun.COM 				pg_name_r = NULL;
644811750SAntonello.Cruz@Sun.COM 				free(pg_type_r);
644911750SAntonello.Cruz@Sun.COM 				pg_type_r = NULL;
64507887SLiane.Praza@Sun.COM 				free(target);
64517887SLiane.Praza@Sun.COM 				target = NULL;
64527887SLiane.Praza@Sun.COM 				break;
64537887SLiane.Praza@Sun.COM 			}
64547887SLiane.Praza@Sun.COM 			free(pg_name_r);
64557887SLiane.Praza@Sun.COM 			pg_name_r = NULL;
645611750SAntonello.Cruz@Sun.COM 			free(pg_type_r);
645711750SAntonello.Cruz@Sun.COM 			pg_type_r = NULL;
64587887SLiane.Praza@Sun.COM 			free(target);
64597887SLiane.Praza@Sun.COM 			target = NULL;
64607887SLiane.Praza@Sun.COM 		}
64617887SLiane.Praza@Sun.COM 		if (ret == -1)
64627887SLiane.Praza@Sun.COM 			goto cleanup;
64637887SLiane.Praza@Sun.COM 		scf_tmpl_pg_reset(r);
64647887SLiane.Praza@Sun.COM 
64657887SLiane.Praza@Sun.COM 		free(pg_name);
64667887SLiane.Praza@Sun.COM 		free(pg_type);
64677887SLiane.Praza@Sun.COM 		pg_name = NULL;
64687887SLiane.Praza@Sun.COM 		pg_type = NULL;
64697887SLiane.Praza@Sun.COM 	}
64707887SLiane.Praza@Sun.COM 	if (ret == -1)
64717887SLiane.Praza@Sun.COM 		goto cleanup;
64727887SLiane.Praza@Sun.COM 
64737887SLiane.Praza@Sun.COM 	ret_val = 0;
64747887SLiane.Praza@Sun.COM 
64757887SLiane.Praza@Sun.COM cleanup:
64767887SLiane.Praza@Sun.COM 	scf_tmpl_pg_destroy(t);
64777887SLiane.Praza@Sun.COM 	scf_tmpl_pg_destroy(r);
64787887SLiane.Praza@Sun.COM 	free(pg_name);
64797887SLiane.Praza@Sun.COM 	free(pg_type);
64807887SLiane.Praza@Sun.COM 	free(pg_name_r);
64817887SLiane.Praza@Sun.COM 	free(pg_type_r);
64827887SLiane.Praza@Sun.COM 	free(target);
64837887SLiane.Praza@Sun.COM 
64847887SLiane.Praza@Sun.COM 	if (ret_val == -1) {
64857887SLiane.Praza@Sun.COM 		if (!ismember(scf_error(), errors_server)) {
64867887SLiane.Praza@Sun.COM 			switch (scf_error()) {
64877887SLiane.Praza@Sun.COM 			case SCF_ERROR_TYPE_MISMATCH:
64887887SLiane.Praza@Sun.COM 				(void) scf_set_error(
64897887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
64907887SLiane.Praza@Sun.COM 				/*FALLTHROUGH*/
64917887SLiane.Praza@Sun.COM 
64927887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
64937887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
64947887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
64957887SLiane.Praza@Sun.COM 			case SCF_ERROR_TEMPLATE_INVALID:
64967887SLiane.Praza@Sun.COM 				break;
64977887SLiane.Praza@Sun.COM 
64987887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
64997887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
65007887SLiane.Praza@Sun.COM 			default:
65017887SLiane.Praza@Sun.COM 				assert(0);
65027887SLiane.Praza@Sun.COM 				abort();
65037887SLiane.Praza@Sun.COM 			}
65047887SLiane.Praza@Sun.COM 		}
65057887SLiane.Praza@Sun.COM 	}
65067887SLiane.Praza@Sun.COM 	return (ret_val);
65077887SLiane.Praza@Sun.COM }
65087887SLiane.Praza@Sun.COM 
65097887SLiane.Praza@Sun.COM /*
65107887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
65117887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
65127887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
65137887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
65147887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
65157887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
65167887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
65177887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
65187887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
65197887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
65207887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
65217887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
65227887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
65237887SLiane.Praza@Sun.COM  */
65247887SLiane.Praza@Sun.COM int
scf_tmpl_validate_fmri(scf_handle_t * h,const char * fmri,const char * snapshot,scf_tmpl_errors_t ** errs,int flags)65257887SLiane.Praza@Sun.COM scf_tmpl_validate_fmri(scf_handle_t *h, const char *fmri, const char *snapshot,
65267887SLiane.Praza@Sun.COM     scf_tmpl_errors_t **errs, int flags)
65277887SLiane.Praza@Sun.COM {
65287887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *t = NULL;
65297887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
65307887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
65317887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
65327887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
65337887SLiane.Praza@Sun.COM 	char *type = NULL;
65347887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
65357887SLiane.Praza@Sun.COM 	ssize_t rsize = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
65367887SLiane.Praza@Sun.COM 	ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
65377887SLiane.Praza@Sun.COM 	int ret = -1;
65387887SLiane.Praza@Sun.COM 	int r;
65397887SLiane.Praza@Sun.COM 
65407887SLiane.Praza@Sun.COM 	assert(errs != NULL);
65417887SLiane.Praza@Sun.COM 
65427887SLiane.Praza@Sun.COM 	if ((*errs = _scf_create_errors(fmri, 1)) == NULL)
65437887SLiane.Praza@Sun.COM 		return (-1);
65447887SLiane.Praza@Sun.COM 
65457887SLiane.Praza@Sun.COM 	if ((pg = scf_pg_create(h)) == NULL ||
65467887SLiane.Praza@Sun.COM 	    (iter = scf_iter_create(h)) == NULL ||
65477887SLiane.Praza@Sun.COM 	    (inst = scf_instance_create(h)) == NULL ||
65487887SLiane.Praza@Sun.COM 	    (t = scf_tmpl_pg_create(h)) == NULL) {
65497887SLiane.Praza@Sun.COM 		/*
65507887SLiane.Praza@Sun.COM 		 * Sets SCF_ERROR_INVALID_ARGUMENT, SCF_ERROR_NO_MEMORY,
65517887SLiane.Praza@Sun.COM 		 * SCF_ERROR_NO_RESOURCES, SCF_ERROR_INTERNAL or
65527887SLiane.Praza@Sun.COM 		 * SCF_ERROR_HANDLE_DESTROYED.
65537887SLiane.Praza@Sun.COM 		 */
65547887SLiane.Praza@Sun.COM 		goto cleanup;
65557887SLiane.Praza@Sun.COM 	}
65567887SLiane.Praza@Sun.COM 
65577887SLiane.Praza@Sun.COM 	if ((type = malloc(rsize)) == NULL ||
65587887SLiane.Praza@Sun.COM 	    (pg_name = malloc(nsize)) == NULL) {
65597887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
65607887SLiane.Praza@Sun.COM 		goto cleanup;
65617887SLiane.Praza@Sun.COM 	}
65627887SLiane.Praza@Sun.COM 
65637887SLiane.Praza@Sun.COM 	if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, NULL,
65647887SLiane.Praza@Sun.COM 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
65657887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
65667887SLiane.Praza@Sun.COM 			goto cleanup;
65677887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
65687887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
65697887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
65707887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
65717887SLiane.Praza@Sun.COM 
65727887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
65737887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
65747887SLiane.Praza@Sun.COM 			goto cleanup;
65757887SLiane.Praza@Sun.COM 
65767887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
65777887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
65787887SLiane.Praza@Sun.COM 		default:
65797887SLiane.Praza@Sun.COM 			assert(0);
65807887SLiane.Praza@Sun.COM 			abort();
65817887SLiane.Praza@Sun.COM 		}
65827887SLiane.Praza@Sun.COM 	}
65837887SLiane.Praza@Sun.COM 
65847887SLiane.Praza@Sun.COM 	if (snapshot == NULL || strcmp(snapshot, "running") == 0 ||
65857887SLiane.Praza@Sun.COM 	    (flags & SCF_TMPL_VALIDATE_FLAG_CURRENT)) {
65867887SLiane.Praza@Sun.COM 		if (_get_snapshot(inst, NULL, &snap) == -1)
65877887SLiane.Praza@Sun.COM 			goto cleanup;
65887887SLiane.Praza@Sun.COM 	} else {
65897887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NONE);
65907887SLiane.Praza@Sun.COM 		if (_get_snapshot(inst, snapshot, &snap) == -1) {
65917887SLiane.Praza@Sun.COM 			goto cleanup;
65927887SLiane.Praza@Sun.COM 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
65937887SLiane.Praza@Sun.COM 			goto cleanup;
65947887SLiane.Praza@Sun.COM 		}
65957887SLiane.Praza@Sun.COM 	}
65967887SLiane.Praza@Sun.COM 	if (_scf_tmpl_check_pg_redef(h, fmri, snapshot, *errs) != 0) {
65977887SLiane.Praza@Sun.COM 		goto cleanup;
65987887SLiane.Praza@Sun.COM 	}
65997887SLiane.Praza@Sun.COM 
66007887SLiane.Praza@Sun.COM 	/*
66017887SLiane.Praza@Sun.COM 	 * Check that property groups on this instance conform to the template.
66027887SLiane.Praza@Sun.COM 	 */
66037887SLiane.Praza@Sun.COM 	if (scf_iter_instance_pgs_composed(iter, inst, snap) != 0) {
66047887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
66057887SLiane.Praza@Sun.COM 			goto cleanup;
66067887SLiane.Praza@Sun.COM 		} else {
66077887SLiane.Praza@Sun.COM 			assert(0);
66087887SLiane.Praza@Sun.COM 			abort();
66097887SLiane.Praza@Sun.COM 		}
66107887SLiane.Praza@Sun.COM 	}
66117887SLiane.Praza@Sun.COM 
66127887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_pg(iter, pg)) == 1) {
66137887SLiane.Praza@Sun.COM 		if (scf_pg_get_name(pg, pg_name, nsize) == -1) {
66147887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
66157887SLiane.Praza@Sun.COM 				goto cleanup;
66167887SLiane.Praza@Sun.COM 			} else {
66177887SLiane.Praza@Sun.COM 				assert(0);
66187887SLiane.Praza@Sun.COM 				abort();
66197887SLiane.Praza@Sun.COM 			}
66207887SLiane.Praza@Sun.COM 		}
66217887SLiane.Praza@Sun.COM 
66227887SLiane.Praza@Sun.COM 		if (scf_pg_get_type(pg, type, rsize) == -1) {
66237887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
66247887SLiane.Praza@Sun.COM 				goto cleanup;
66257887SLiane.Praza@Sun.COM 			} else {
66267887SLiane.Praza@Sun.COM 				assert(0);
66277887SLiane.Praza@Sun.COM 				abort();
66287887SLiane.Praza@Sun.COM 			}
66297887SLiane.Praza@Sun.COM 		}
66307887SLiane.Praza@Sun.COM 
66317887SLiane.Praza@Sun.COM 		if (scf_tmpl_get_by_pg_name(fmri, snapshot, pg_name, type, t,
66327887SLiane.Praza@Sun.COM 		    0) != 0) {
66337887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
66347887SLiane.Praza@Sun.COM 				goto cleanup;
66357887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
66367887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
66377887SLiane.Praza@Sun.COM 				continue;
66387887SLiane.Praza@Sun.COM 
66397887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
66407887SLiane.Praza@Sun.COM 				goto cleanup;
66417887SLiane.Praza@Sun.COM 
66427887SLiane.Praza@Sun.COM 			default:
66437887SLiane.Praza@Sun.COM 				assert(0);
66447887SLiane.Praza@Sun.COM 				abort();
66457887SLiane.Praza@Sun.COM 			}
66467887SLiane.Praza@Sun.COM 		}
66477887SLiane.Praza@Sun.COM 
66487887SLiane.Praza@Sun.COM 		if (_check_pg(t, pg, pg_name, type, *errs) != 0)
66497887SLiane.Praza@Sun.COM 			goto cleanup;
66507887SLiane.Praza@Sun.COM 	}
66517887SLiane.Praza@Sun.COM 	if (r < 0) {
66527887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
66537887SLiane.Praza@Sun.COM 			goto cleanup;
66547887SLiane.Praza@Sun.COM 		} else {
66557887SLiane.Praza@Sun.COM 			assert(0);
66567887SLiane.Praza@Sun.COM 			abort();
66577887SLiane.Praza@Sun.COM 		}
66587887SLiane.Praza@Sun.COM 	}
66597887SLiane.Praza@Sun.COM 
66607887SLiane.Praza@Sun.COM 	scf_tmpl_pg_reset(t);
66617887SLiane.Praza@Sun.COM 
66627887SLiane.Praza@Sun.COM 	/*
66637887SLiane.Praza@Sun.COM 	 * Confirm required property groups are present.
66647887SLiane.Praza@Sun.COM 	 */
66657887SLiane.Praza@Sun.COM 	while ((r = scf_tmpl_iter_pgs(t, fmri, snapshot, NULL,
66667887SLiane.Praza@Sun.COM 	    SCF_PG_TMPL_FLAG_REQUIRED)) == 1) {
66677887SLiane.Praza@Sun.COM 		free(pg_name);
66687887SLiane.Praza@Sun.COM 		free(type);
66697887SLiane.Praza@Sun.COM 
66707887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_name(t, &pg_name) == -1)
66717887SLiane.Praza@Sun.COM 			goto cleanup;
66727887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_type(t, &type) == -1)
66737887SLiane.Praza@Sun.COM 			goto cleanup;
66747887SLiane.Praza@Sun.COM 		/*
66757887SLiane.Praza@Sun.COM 		 * required property group templates should not have
66767887SLiane.Praza@Sun.COM 		 * wildcarded name or type
66777887SLiane.Praza@Sun.COM 		 */
66787887SLiane.Praza@Sun.COM 		if (strcmp(pg_name, SCF_TMPL_WILDCARD) == 0 ||
66797887SLiane.Praza@Sun.COM 		    strcmp(type, SCF_TMPL_WILDCARD) == 0) {
66807887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
66817887SLiane.Praza@Sun.COM 			goto cleanup;
66827887SLiane.Praza@Sun.COM 		}
66837887SLiane.Praza@Sun.COM 
66847887SLiane.Praza@Sun.COM 		if (_get_pg(NULL, inst, snap, pg_name, pg) != 0) {
66857887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
66867887SLiane.Praza@Sun.COM 				goto cleanup;
66877887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
66887887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
66897887SLiane.Praza@Sun.COM 				if (_add_tmpl_missing_pg_error(*errs, t) == -1)
66907887SLiane.Praza@Sun.COM 					goto cleanup;
66917887SLiane.Praza@Sun.COM 				continue;
66927887SLiane.Praza@Sun.COM 
66937887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
66947887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
66957887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
66967887SLiane.Praza@Sun.COM 			default:
66977887SLiane.Praza@Sun.COM 				assert(0);
66987887SLiane.Praza@Sun.COM 				abort();
66997887SLiane.Praza@Sun.COM 			}
67007887SLiane.Praza@Sun.COM 		}
67017887SLiane.Praza@Sun.COM 	}
67027887SLiane.Praza@Sun.COM 	if (r < 0) {
67037887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
67047887SLiane.Praza@Sun.COM 			goto cleanup;
67057887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
67067887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
67077887SLiane.Praza@Sun.COM 			break;
67087887SLiane.Praza@Sun.COM 
67097887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
67107887SLiane.Praza@Sun.COM 			goto cleanup;
67117887SLiane.Praza@Sun.COM 
67127887SLiane.Praza@Sun.COM 		default:
67137887SLiane.Praza@Sun.COM 			assert(0);
67147887SLiane.Praza@Sun.COM 			abort();
67157887SLiane.Praza@Sun.COM 		}
67167887SLiane.Praza@Sun.COM 	}
67177887SLiane.Praza@Sun.COM 
67187887SLiane.Praza@Sun.COM 	ret = 0;
67197887SLiane.Praza@Sun.COM 	if ((*errs)->tes_num_errs > 0)
67207887SLiane.Praza@Sun.COM 		ret = 1;
67217887SLiane.Praza@Sun.COM cleanup:
67227887SLiane.Praza@Sun.COM 	if (ret != 1) {
67237887SLiane.Praza@Sun.COM 		/* there are no errors to report */
67247887SLiane.Praza@Sun.COM 		scf_tmpl_errors_destroy(*errs);
67257887SLiane.Praza@Sun.COM 		*errs = NULL;
67267887SLiane.Praza@Sun.COM 	}
67277887SLiane.Praza@Sun.COM 	scf_tmpl_pg_destroy(t);
67287887SLiane.Praza@Sun.COM 	free(type);
67297887SLiane.Praza@Sun.COM 	free(pg_name);
67307887SLiane.Praza@Sun.COM 
67317887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
67327887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
67337887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
67347887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
67357887SLiane.Praza@Sun.COM 
67367887SLiane.Praza@Sun.COM 	return (ret);
67377887SLiane.Praza@Sun.COM }
67387887SLiane.Praza@Sun.COM 
67397887SLiane.Praza@Sun.COM void
scf_tmpl_errors_destroy(scf_tmpl_errors_t * errs)67407887SLiane.Praza@Sun.COM scf_tmpl_errors_destroy(scf_tmpl_errors_t *errs)
67417887SLiane.Praza@Sun.COM {
67427887SLiane.Praza@Sun.COM 	int i;
67437887SLiane.Praza@Sun.COM 	scf_tmpl_error_t *e;
67447887SLiane.Praza@Sun.COM 
67457887SLiane.Praza@Sun.COM 	if (errs == NULL)
67467887SLiane.Praza@Sun.COM 		return;
67477887SLiane.Praza@Sun.COM 
67487887SLiane.Praza@Sun.COM 	for (i = 0; i < errs->tes_num_errs; ++i) {
67497887SLiane.Praza@Sun.COM 		e = errs->tes_errs[i];
67507887SLiane.Praza@Sun.COM 		if (errs->tes_flag != 0) {
67517887SLiane.Praza@Sun.COM 			free((char *)e->te_pg_name);
67527887SLiane.Praza@Sun.COM 			free((char *)e->te_prop_name);
67537887SLiane.Praza@Sun.COM 			free((char *)e->te_ev1);
67547887SLiane.Praza@Sun.COM 			free((char *)e->te_ev2);
67557887SLiane.Praza@Sun.COM 			free((char *)e->te_actual);
67567887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_fmri);
67577887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_pg_name);
67587887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_pg_type);
67597887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_prop_name);
67607887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_prop_type);
67617887SLiane.Praza@Sun.COM 		}
67627887SLiane.Praza@Sun.COM 		free(e);
67637887SLiane.Praza@Sun.COM 	}
67647887SLiane.Praza@Sun.COM 	free((char *)errs->tes_fmri);
67657887SLiane.Praza@Sun.COM 	free((char *)errs->tes_prefix);
67667887SLiane.Praza@Sun.COM 	free(errs->tes_errs);
67677887SLiane.Praza@Sun.COM 	free(errs);
67687887SLiane.Praza@Sun.COM }
67697887SLiane.Praza@Sun.COM 
67707887SLiane.Praza@Sun.COM int
scf_tmpl_error_source_fmri(const scf_tmpl_error_t * err,char ** fmri)67717887SLiane.Praza@Sun.COM scf_tmpl_error_source_fmri(const scf_tmpl_error_t *err, char **fmri)
67727887SLiane.Praza@Sun.COM {
67737887SLiane.Praza@Sun.COM 	assert(err != NULL);
67747887SLiane.Praza@Sun.COM 	switch (err->te_type) {
67757887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
67767887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
67777887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
67787887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
67797887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
67807887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
67817887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
67827887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
67837887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
67847887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
67857887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
67867887SLiane.Praza@Sun.COM 		*fmri = (char *)err->te_tmpl_fmri;
67877887SLiane.Praza@Sun.COM 		return (0);
67887887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
67897887SLiane.Praza@Sun.COM 	default:
67907887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
67917887SLiane.Praza@Sun.COM 	}
67927887SLiane.Praza@Sun.COM 	return (-1);
67937887SLiane.Praza@Sun.COM }
67947887SLiane.Praza@Sun.COM 
67957887SLiane.Praza@Sun.COM int
scf_tmpl_error_type(const scf_tmpl_error_t * err,scf_tmpl_error_type_t * type)67967887SLiane.Praza@Sun.COM scf_tmpl_error_type(const scf_tmpl_error_t *err, scf_tmpl_error_type_t *type)
67977887SLiane.Praza@Sun.COM {
67987887SLiane.Praza@Sun.COM 	assert(err != NULL);
67997887SLiane.Praza@Sun.COM 	switch (err->te_type) {
68007887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
68017887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
68027887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
68037887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
68047887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
68057887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
68067887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
68077887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
68087887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
68097887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
68107887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
68117887SLiane.Praza@Sun.COM 		*type = err->te_type;
68127887SLiane.Praza@Sun.COM 		return (0);
68137887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
68147887SLiane.Praza@Sun.COM 	default:
68157887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
68167887SLiane.Praza@Sun.COM 	}
68177887SLiane.Praza@Sun.COM 	return (-1);
68187887SLiane.Praza@Sun.COM }
68197887SLiane.Praza@Sun.COM 
68207887SLiane.Praza@Sun.COM int
scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t * err,char ** name,char ** type)68217887SLiane.Praza@Sun.COM scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t *err, char **name, char **type)
68227887SLiane.Praza@Sun.COM {
68237887SLiane.Praza@Sun.COM 	assert(err != NULL);
68247887SLiane.Praza@Sun.COM 	switch (err->te_type) {
68257887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
68267887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
68277887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
68287887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
68297887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
68307887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
68317887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
68327887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
68337887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
68347887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
68357887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
68367887SLiane.Praza@Sun.COM 		if (err->te_tmpl_pg_name != NULL &&
68377887SLiane.Praza@Sun.COM 		    err->te_tmpl_pg_type != NULL) {
68387887SLiane.Praza@Sun.COM 			if (name != NULL)
68397887SLiane.Praza@Sun.COM 				*name = (char *)err->te_tmpl_pg_name;
68407887SLiane.Praza@Sun.COM 			if (type != NULL)
68417887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_pg_type;
68427887SLiane.Praza@Sun.COM 			return (0);
68437887SLiane.Praza@Sun.COM 		}
68447887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
68457887SLiane.Praza@Sun.COM 		break;
68467887SLiane.Praza@Sun.COM 	default:
68477887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
68487887SLiane.Praza@Sun.COM 	}
68497887SLiane.Praza@Sun.COM 	return (-1);
68507887SLiane.Praza@Sun.COM }
68517887SLiane.Praza@Sun.COM 
68527887SLiane.Praza@Sun.COM int
scf_tmpl_error_pg(const scf_tmpl_error_t * err,char ** name,char ** type)68537887SLiane.Praza@Sun.COM scf_tmpl_error_pg(const scf_tmpl_error_t *err, char **name, char **type)
68547887SLiane.Praza@Sun.COM {
68557887SLiane.Praza@Sun.COM 	assert(err != NULL);
68567887SLiane.Praza@Sun.COM 	switch (err->te_type) {
68577887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
68587887SLiane.Praza@Sun.COM 		if (err->te_pg_name != NULL &&
68597887SLiane.Praza@Sun.COM 		    err->te_actual != NULL) {
68607887SLiane.Praza@Sun.COM 			if (name != NULL)
68617887SLiane.Praza@Sun.COM 				*name = (char *)err->te_pg_name;
68627887SLiane.Praza@Sun.COM 			if (type != NULL)
68637887SLiane.Praza@Sun.COM 				*type = (char *)err->te_actual;
68647887SLiane.Praza@Sun.COM 			return (0);
68657887SLiane.Praza@Sun.COM 		}
68667887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
68677887SLiane.Praza@Sun.COM 		break;
68687887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
68697887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
68707887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
68717887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
68727887SLiane.Praza@Sun.COM 		if (err->te_pg_name != NULL &&
68737887SLiane.Praza@Sun.COM 		    err->te_tmpl_pg_type != NULL) {
68747887SLiane.Praza@Sun.COM 			if (name != NULL)
68757887SLiane.Praza@Sun.COM 				*name = (char *)err->te_pg_name;
68767887SLiane.Praza@Sun.COM 			if (type != NULL)
68777887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_pg_type;
68787887SLiane.Praza@Sun.COM 			return (0);
68797887SLiane.Praza@Sun.COM 		}
68807887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
68817887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
68827887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
68837887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
68847887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
68857887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
68867887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
68877887SLiane.Praza@Sun.COM 		break;
68887887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
68897887SLiane.Praza@Sun.COM 		if (err->te_ev1 != NULL && err->te_ev2 != NULL) {
68907887SLiane.Praza@Sun.COM 			if (name != NULL)
68917887SLiane.Praza@Sun.COM 				*name = (char *)err->te_ev1;
68927887SLiane.Praza@Sun.COM 			if (type != NULL)
68937887SLiane.Praza@Sun.COM 				*type = (char *)err->te_ev2;
68947887SLiane.Praza@Sun.COM 			return (0);
68957887SLiane.Praza@Sun.COM 		}
68967887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
68977887SLiane.Praza@Sun.COM 		break;
68987887SLiane.Praza@Sun.COM 	default:
68997887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
69007887SLiane.Praza@Sun.COM 	}
69017887SLiane.Praza@Sun.COM 	return (-1);
69027887SLiane.Praza@Sun.COM }
69037887SLiane.Praza@Sun.COM 
69047887SLiane.Praza@Sun.COM int
scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t * err,char ** name,char ** type)69057887SLiane.Praza@Sun.COM scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t *err, char **name, char **type)
69067887SLiane.Praza@Sun.COM {
69077887SLiane.Praza@Sun.COM 	assert(err != NULL);
69087887SLiane.Praza@Sun.COM 	switch (err->te_type) {
69097887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
69107887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
69117887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
69127887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
69137887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
69147887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
69157887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
69167887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
69177887SLiane.Praza@Sun.COM 		if (err->te_tmpl_prop_name != NULL &&
69187887SLiane.Praza@Sun.COM 		    err->te_tmpl_prop_type != NULL) {
69197887SLiane.Praza@Sun.COM 			if (name != NULL)
69207887SLiane.Praza@Sun.COM 				*name = (char *)err->te_tmpl_prop_name;
69217887SLiane.Praza@Sun.COM 			if (type != NULL)
69227887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_prop_type;
69237887SLiane.Praza@Sun.COM 			return (0);
69247887SLiane.Praza@Sun.COM 		}
69257887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
69267887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
69277887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
69287887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
69297887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
69307887SLiane.Praza@Sun.COM 		break;
69317887SLiane.Praza@Sun.COM 	default:
69327887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
69337887SLiane.Praza@Sun.COM 	}
69347887SLiane.Praza@Sun.COM 	return (-1);
69357887SLiane.Praza@Sun.COM }
69367887SLiane.Praza@Sun.COM 
69377887SLiane.Praza@Sun.COM int
scf_tmpl_error_prop(const scf_tmpl_error_t * err,char ** name,char ** type)69387887SLiane.Praza@Sun.COM scf_tmpl_error_prop(const scf_tmpl_error_t *err, char **name, char **type)
69397887SLiane.Praza@Sun.COM {
69407887SLiane.Praza@Sun.COM 	assert(err != NULL);
69417887SLiane.Praza@Sun.COM 	switch (err->te_type) {
69427887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
69437887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
69447887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
69457887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
69467887SLiane.Praza@Sun.COM 		if (err->te_prop_name != NULL &&
69477887SLiane.Praza@Sun.COM 		    err->te_tmpl_prop_type != NULL) {
69487887SLiane.Praza@Sun.COM 			if (name != NULL)
69497887SLiane.Praza@Sun.COM 				*name = (char *)err->te_prop_name;
69507887SLiane.Praza@Sun.COM 			if (type != NULL)
69517887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_prop_type;
69527887SLiane.Praza@Sun.COM 			return (0);
69537887SLiane.Praza@Sun.COM 		}
69547887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
69557887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
69567887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
69577887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
69587887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
69597887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
69607887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
69617887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
69627887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
69637887SLiane.Praza@Sun.COM 		break;
69647887SLiane.Praza@Sun.COM 	default:
69657887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
69667887SLiane.Praza@Sun.COM 	}
69677887SLiane.Praza@Sun.COM 	return (-1);
69687887SLiane.Praza@Sun.COM }
69697887SLiane.Praza@Sun.COM 
69707887SLiane.Praza@Sun.COM int
scf_tmpl_error_value(const scf_tmpl_error_t * err,char ** val)69717887SLiane.Praza@Sun.COM scf_tmpl_error_value(const scf_tmpl_error_t *err, char **val)
69727887SLiane.Praza@Sun.COM {
69737887SLiane.Praza@Sun.COM 	assert(err != NULL);
69747887SLiane.Praza@Sun.COM 	switch (err->te_type) {
69757887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
69767887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
69777887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
69787887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
69797887SLiane.Praza@Sun.COM 		if (err->te_actual != NULL) {
69807887SLiane.Praza@Sun.COM 			if (val != NULL)
69817887SLiane.Praza@Sun.COM 				*val = (char *)err->te_actual;
69827887SLiane.Praza@Sun.COM 			return (0);
69837887SLiane.Praza@Sun.COM 		}
69847887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
69857887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
69867887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
69877887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
69887887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
69897887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
69907887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
69917887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
69927887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
69937887SLiane.Praza@Sun.COM 		break;
69947887SLiane.Praza@Sun.COM 	default:
69957887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
69967887SLiane.Praza@Sun.COM 	}
69977887SLiane.Praza@Sun.COM 	return (-1);
69987887SLiane.Praza@Sun.COM }
69997887SLiane.Praza@Sun.COM 
70007887SLiane.Praza@Sun.COM const char *
scf_tmpl_visibility_to_string(uint8_t vis)70017887SLiane.Praza@Sun.COM scf_tmpl_visibility_to_string(uint8_t vis)
70027887SLiane.Praza@Sun.COM {
70037887SLiane.Praza@Sun.COM 	if (vis == SCF_TMPL_VISIBILITY_READONLY)
70047887SLiane.Praza@Sun.COM 		return (SCF_TM_VISIBILITY_READONLY);
70057887SLiane.Praza@Sun.COM 	else if (vis == SCF_TMPL_VISIBILITY_HIDDEN)
70067887SLiane.Praza@Sun.COM 		return (SCF_TM_VISIBILITY_HIDDEN);
70077887SLiane.Praza@Sun.COM 	else if (vis == SCF_TMPL_VISIBILITY_READWRITE)
70087887SLiane.Praza@Sun.COM 		return (SCF_TM_VISIBILITY_READWRITE);
70097887SLiane.Praza@Sun.COM 	else
70107887SLiane.Praza@Sun.COM 		return ("unknown");
70117887SLiane.Praza@Sun.COM }
7012