1*7887SLiane.Praza@Sun.COM /*
2*7887SLiane.Praza@Sun.COM  * CDDL HEADER START
3*7887SLiane.Praza@Sun.COM  *
4*7887SLiane.Praza@Sun.COM  * The contents of this file are subject to the terms of the
5*7887SLiane.Praza@Sun.COM  * Common Development and Distribution License (the "License").
6*7887SLiane.Praza@Sun.COM  * You may not use this file except in compliance with the License.
7*7887SLiane.Praza@Sun.COM  *
8*7887SLiane.Praza@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7887SLiane.Praza@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7887SLiane.Praza@Sun.COM  * See the License for the specific language governing permissions
11*7887SLiane.Praza@Sun.COM  * and limitations under the License.
12*7887SLiane.Praza@Sun.COM  *
13*7887SLiane.Praza@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7887SLiane.Praza@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7887SLiane.Praza@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7887SLiane.Praza@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7887SLiane.Praza@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7887SLiane.Praza@Sun.COM  *
19*7887SLiane.Praza@Sun.COM  * CDDL HEADER END
20*7887SLiane.Praza@Sun.COM  */
21*7887SLiane.Praza@Sun.COM /*
22*7887SLiane.Praza@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7887SLiane.Praza@Sun.COM  * Use is subject to license terms.
24*7887SLiane.Praza@Sun.COM  */
25*7887SLiane.Praza@Sun.COM 
26*7887SLiane.Praza@Sun.COM /*
27*7887SLiane.Praza@Sun.COM  * scf_tmpl.c
28*7887SLiane.Praza@Sun.COM  *
29*7887SLiane.Praza@Sun.COM  * This file implements the bulk of the libscf templates interfaces.
30*7887SLiane.Praza@Sun.COM  * Templates describe metadata about a service or instance in general,
31*7887SLiane.Praza@Sun.COM  * and individual configuration properties on those services and instances.
32*7887SLiane.Praza@Sun.COM  * Human-consumable descriptions can be provided, along with definitions
33*7887SLiane.Praza@Sun.COM  * of valid configuration.  See service_bundle.dtd.1 for XML definitions
34*7887SLiane.Praza@Sun.COM  * of templates, and the svccfg code for information on how those definitions
35*7887SLiane.Praza@Sun.COM  * are translated into the repository.
36*7887SLiane.Praza@Sun.COM  *
37*7887SLiane.Praza@Sun.COM  * The main data structures are scf_pg_tmpl and scf_prop_tmpl.  These
38*7887SLiane.Praza@Sun.COM  * are allocated by the callers through scf_tmpl_[pg|prop]_create(), and
39*7887SLiane.Praza@Sun.COM  * destroyed with scf_tmpl_[pg|prop]_destroy().  They are populated by
40*7887SLiane.Praza@Sun.COM  * scf_tmpl_get_by_pg_name(), scf_tmpl_get_by_pg(), and
41*7887SLiane.Praza@Sun.COM  * scf_tmpl_get_by_prop().  They also store the iterator state for
42*7887SLiane.Praza@Sun.COM  * scf_tmpl_iter_pgs() and scf_tmpl_iter_props().
43*7887SLiane.Praza@Sun.COM  *
44*7887SLiane.Praza@Sun.COM  * These data structures are then consumed by other functions to
45*7887SLiane.Praza@Sun.COM  * gather information about the template (e.g. name, description,
46*7887SLiane.Praza@Sun.COM  * choices, constraints, etc.).
47*7887SLiane.Praza@Sun.COM  *
48*7887SLiane.Praza@Sun.COM  * scf_tmpl_validate_fmri() does instance validation against template
49*7887SLiane.Praza@Sun.COM  * data, and populates a set of template errors which can be explored using
50*7887SLiane.Praza@Sun.COM  * the scf_tmpl_next_error() and the scf_tmpl_error*() suite of functions.
51*7887SLiane.Praza@Sun.COM  *
52*7887SLiane.Praza@Sun.COM  * The main data structures for template errors are scf_tmpl_errors,
53*7887SLiane.Praza@Sun.COM  * defined in this file, and scf_tmpl_error, defined in libscf_priv.h.
54*7887SLiane.Praza@Sun.COM  * scf_tmpl_error is shared with svccfg to offer common printing
55*7887SLiane.Praza@Sun.COM  * of error messages between libscf and svccfg.
56*7887SLiane.Praza@Sun.COM  *
57*7887SLiane.Praza@Sun.COM  * General convenience functions are towards the top of this file,
58*7887SLiane.Praza@Sun.COM  * followed by pg and prop template discovery functions, followed
59*7887SLiane.Praza@Sun.COM  * by functions which gather information about the discovered
60*7887SLiane.Praza@Sun.COM  * template.  Validation and error functions are at the end of this file.
61*7887SLiane.Praza@Sun.COM  */
62*7887SLiane.Praza@Sun.COM 
63*7887SLiane.Praza@Sun.COM #include "lowlevel_impl.h"
64*7887SLiane.Praza@Sun.COM #include "libscf_impl.h"
65*7887SLiane.Praza@Sun.COM #include <assert.h>
66*7887SLiane.Praza@Sun.COM #include <errno.h>
67*7887SLiane.Praza@Sun.COM #include <libintl.h>
68*7887SLiane.Praza@Sun.COM #include <stdlib.h>
69*7887SLiane.Praza@Sun.COM #include <stdio.h>
70*7887SLiane.Praza@Sun.COM #include <strings.h>
71*7887SLiane.Praza@Sun.COM #include <locale.h>
72*7887SLiane.Praza@Sun.COM #include <ctype.h>
73*7887SLiane.Praza@Sun.COM #include <inttypes.h>
74*7887SLiane.Praza@Sun.COM 
75*7887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_COMMON_NAME_C	"common_name_C"
76*7887SLiane.Praza@Sun.COM 
77*7887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_NONE		0
78*7887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_INST		1
79*7887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_RESTARTER	2
80*7887SLiane.Praza@Sun.COM #define	SCF__TMPL_ITER_GLOBAL		3
81*7887SLiane.Praza@Sun.COM 
82*7887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_NT		0
83*7887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_N		1
84*7887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_T		2
85*7887SLiane.Praza@Sun.COM #define	SCF_TMPL_PG_WILD	3
86*7887SLiane.Praza@Sun.COM 
87*7887SLiane.Praza@Sun.COM struct scf_pg_tmpl {
88*7887SLiane.Praza@Sun.COM 	int pt_populated;
89*7887SLiane.Praza@Sun.COM 	scf_handle_t *pt_h;
90*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pt_pg;
91*7887SLiane.Praza@Sun.COM 	scf_service_t *pt_orig_svc;
92*7887SLiane.Praza@Sun.COM 	scf_service_t *pt_svc;
93*7887SLiane.Praza@Sun.COM 	scf_instance_t *pt_orig_inst;
94*7887SLiane.Praza@Sun.COM 	scf_instance_t *pt_inst;
95*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *pt_snap;
96*7887SLiane.Praza@Sun.COM 	int pt_is_iter;
97*7887SLiane.Praza@Sun.COM 	scf_iter_t *pt_iter;
98*7887SLiane.Praza@Sun.COM 	int pt_iter_last;
99*7887SLiane.Praza@Sun.COM };
100*7887SLiane.Praza@Sun.COM 
101*7887SLiane.Praza@Sun.COM #define	SCF_WALK_ERROR		-1
102*7887SLiane.Praza@Sun.COM #define	SCF_WALK_NEXT		0
103*7887SLiane.Praza@Sun.COM #define	SCF_WALK_DONE		1
104*7887SLiane.Praza@Sun.COM 
105*7887SLiane.Praza@Sun.COM struct pg_tmpl_walk {
106*7887SLiane.Praza@Sun.COM 	const char *pw_snapname;
107*7887SLiane.Praza@Sun.COM 	const char *pw_pgname;
108*7887SLiane.Praza@Sun.COM 	const char *pw_pgtype;
109*7887SLiane.Praza@Sun.COM 	scf_instance_t *pw_inst;
110*7887SLiane.Praza@Sun.COM 	scf_service_t *pw_svc;
111*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *pw_snap;
112*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pw_pg;
113*7887SLiane.Praza@Sun.COM 	const char *pw_target;
114*7887SLiane.Praza@Sun.COM 	char *pw_tmpl_pgname;
115*7887SLiane.Praza@Sun.COM };
116*7887SLiane.Praza@Sun.COM 
117*7887SLiane.Praza@Sun.COM typedef struct pg_tmpl_walk pg_tmpl_walk_t;
118*7887SLiane.Praza@Sun.COM 
119*7887SLiane.Praza@Sun.COM typedef int walk_template_inst_func_t(scf_service_t *_svc,
120*7887SLiane.Praza@Sun.COM     scf_instance_t *_inst, pg_tmpl_walk_t *p);
121*7887SLiane.Praza@Sun.COM 
122*7887SLiane.Praza@Sun.COM struct scf_prop_tmpl {
123*7887SLiane.Praza@Sun.COM 	int prt_populated;
124*7887SLiane.Praza@Sun.COM 	scf_handle_t *prt_h;
125*7887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *prt_t;
126*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *prt_pg;
127*7887SLiane.Praza@Sun.COM 	char *prt_pg_name;
128*7887SLiane.Praza@Sun.COM 	scf_iter_t *prt_iter;
129*7887SLiane.Praza@Sun.COM };
130*7887SLiane.Praza@Sun.COM 
131*7887SLiane.Praza@Sun.COM /*
132*7887SLiane.Praza@Sun.COM  * Common server errors are usually passed back to the caller.  This
133*7887SLiane.Praza@Sun.COM  * array defines them centrally so that they don't need to be enumerated
134*7887SLiane.Praza@Sun.COM  * in every libscf call.
135*7887SLiane.Praza@Sun.COM  */
136*7887SLiane.Praza@Sun.COM static const scf_error_t errors_server[] = {
137*7887SLiane.Praza@Sun.COM 	SCF_ERROR_BACKEND_ACCESS,
138*7887SLiane.Praza@Sun.COM 	SCF_ERROR_CONNECTION_BROKEN,
139*7887SLiane.Praza@Sun.COM 	SCF_ERROR_DELETED,
140*7887SLiane.Praza@Sun.COM 	SCF_ERROR_HANDLE_DESTROYED,
141*7887SLiane.Praza@Sun.COM 	SCF_ERROR_INTERNAL,
142*7887SLiane.Praza@Sun.COM 	SCF_ERROR_NO_MEMORY,
143*7887SLiane.Praza@Sun.COM 	SCF_ERROR_NO_RESOURCES,
144*7887SLiane.Praza@Sun.COM 	SCF_ERROR_NOT_BOUND,
145*7887SLiane.Praza@Sun.COM 	SCF_ERROR_PERMISSION_DENIED,
146*7887SLiane.Praza@Sun.COM 	0
147*7887SLiane.Praza@Sun.COM 	};
148*7887SLiane.Praza@Sun.COM 
149*7887SLiane.Praza@Sun.COM /*
150*7887SLiane.Praza@Sun.COM  * int ismember()
151*7887SLiane.Praza@Sun.COM  *
152*7887SLiane.Praza@Sun.COM  * Returns 1 if the supplied error is a member of the error array, 0
153*7887SLiane.Praza@Sun.COM  * if it is not.
154*7887SLiane.Praza@Sun.COM  */
155*7887SLiane.Praza@Sun.COM static scf_error_t
156*7887SLiane.Praza@Sun.COM ismember(const int error, const scf_error_t error_array[])
157*7887SLiane.Praza@Sun.COM {
158*7887SLiane.Praza@Sun.COM 	int i;
159*7887SLiane.Praza@Sun.COM 
160*7887SLiane.Praza@Sun.COM 	for (i = 0; error_array[i] != 0; ++i) {
161*7887SLiane.Praza@Sun.COM 		if (error == error_array[i])
162*7887SLiane.Praza@Sun.COM 			return (1);
163*7887SLiane.Praza@Sun.COM 	}
164*7887SLiane.Praza@Sun.COM 
165*7887SLiane.Praza@Sun.COM 	return (0);
166*7887SLiane.Praza@Sun.COM }
167*7887SLiane.Praza@Sun.COM 
168*7887SLiane.Praza@Sun.COM /*
169*7887SLiane.Praza@Sun.COM  * char *_scf_tmpl_get_fmri()
170*7887SLiane.Praza@Sun.COM  *
171*7887SLiane.Praza@Sun.COM  * Given a pg_tmpl, returns the FMRI of the service or instance that
172*7887SLiane.Praza@Sun.COM  * template describes.  The allocated string must be freed with free().
173*7887SLiane.Praza@Sun.COM  *
174*7887SLiane.Praza@Sun.COM  * On failure, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
175*7887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
176*7887SLiane.Praza@Sun.COM  */
177*7887SLiane.Praza@Sun.COM static char *
178*7887SLiane.Praza@Sun.COM _scf_tmpl_get_fmri(const scf_pg_tmpl_t *t)
179*7887SLiane.Praza@Sun.COM {
180*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1;
181*7887SLiane.Praza@Sun.COM 	int r;
182*7887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
183*7887SLiane.Praza@Sun.COM 
184*7887SLiane.Praza@Sun.COM 	assert(t->pt_svc != NULL || t->pt_inst != NULL);
185*7887SLiane.Praza@Sun.COM 	assert(t->pt_svc == NULL || t->pt_inst == NULL);
186*7887SLiane.Praza@Sun.COM 
187*7887SLiane.Praza@Sun.COM 	if (buf == NULL) {
188*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
189*7887SLiane.Praza@Sun.COM 		return (buf);
190*7887SLiane.Praza@Sun.COM 	}
191*7887SLiane.Praza@Sun.COM 
192*7887SLiane.Praza@Sun.COM 	if (t->pt_inst != NULL)
193*7887SLiane.Praza@Sun.COM 		r = scf_instance_to_fmri(t->pt_inst, buf, sz);
194*7887SLiane.Praza@Sun.COM 	else
195*7887SLiane.Praza@Sun.COM 		r = scf_service_to_fmri(t->pt_svc, buf, sz);
196*7887SLiane.Praza@Sun.COM 
197*7887SLiane.Praza@Sun.COM 	if (r == -1) {
198*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
199*7887SLiane.Praza@Sun.COM 			free(buf);
200*7887SLiane.Praza@Sun.COM 			buf = NULL;
201*7887SLiane.Praza@Sun.COM 		} else {
202*7887SLiane.Praza@Sun.COM 			assert(0);
203*7887SLiane.Praza@Sun.COM 			abort();
204*7887SLiane.Praza@Sun.COM 		}
205*7887SLiane.Praza@Sun.COM 	}
206*7887SLiane.Praza@Sun.COM 
207*7887SLiane.Praza@Sun.COM 	return (buf);
208*7887SLiane.Praza@Sun.COM }
209*7887SLiane.Praza@Sun.COM 
210*7887SLiane.Praza@Sun.COM /*
211*7887SLiane.Praza@Sun.COM  * char *_scf_get_pg_type()
212*7887SLiane.Praza@Sun.COM  *
213*7887SLiane.Praza@Sun.COM  * Given a propertygroup, returns an allocated string containing the
214*7887SLiane.Praza@Sun.COM  * type.  The string must be freed with free().
215*7887SLiane.Praza@Sun.COM  *
216*7887SLiane.Praza@Sun.COM  * On failure, returns NULL and sets scf_error() to: _CONNECTION_BROKEN,
217*7887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
218*7887SLiane.Praza@Sun.COM  */
219*7887SLiane.Praza@Sun.COM static char *
220*7887SLiane.Praza@Sun.COM _scf_get_pg_type(scf_propertygroup_t *pg)
221*7887SLiane.Praza@Sun.COM {
222*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
223*7887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
224*7887SLiane.Praza@Sun.COM 
225*7887SLiane.Praza@Sun.COM 	if (buf == NULL) {
226*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
227*7887SLiane.Praza@Sun.COM 	} else if (scf_pg_get_type(pg, buf, sz) == -1) {
228*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
229*7887SLiane.Praza@Sun.COM 			free(buf);
230*7887SLiane.Praza@Sun.COM 			buf = NULL;
231*7887SLiane.Praza@Sun.COM 		} else {
232*7887SLiane.Praza@Sun.COM 			assert(0);
233*7887SLiane.Praza@Sun.COM 			abort();
234*7887SLiane.Praza@Sun.COM 		}
235*7887SLiane.Praza@Sun.COM 	}
236*7887SLiane.Praza@Sun.COM 
237*7887SLiane.Praza@Sun.COM 	return (buf);
238*7887SLiane.Praza@Sun.COM }
239*7887SLiane.Praza@Sun.COM 
240*7887SLiane.Praza@Sun.COM /*
241*7887SLiane.Praza@Sun.COM  * char *_scf_get_prop_name()
242*7887SLiane.Praza@Sun.COM  *
243*7887SLiane.Praza@Sun.COM  * Given a property, returns the name in an allocated string.  The string must
244*7887SLiane.Praza@Sun.COM  * be freed with free().
245*7887SLiane.Praza@Sun.COM  *
246*7887SLiane.Praza@Sun.COM  * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
247*7887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
248*7887SLiane.Praza@Sun.COM  */
249*7887SLiane.Praza@Sun.COM static char *
250*7887SLiane.Praza@Sun.COM _scf_get_prop_name(scf_property_t *prop)
251*7887SLiane.Praza@Sun.COM {
252*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
253*7887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
254*7887SLiane.Praza@Sun.COM 
255*7887SLiane.Praza@Sun.COM 	if (buf == NULL) {
256*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
257*7887SLiane.Praza@Sun.COM 	} else if (scf_property_get_name(prop, buf, sz) == -1) {
258*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
259*7887SLiane.Praza@Sun.COM 			free(buf);
260*7887SLiane.Praza@Sun.COM 			buf = NULL;
261*7887SLiane.Praza@Sun.COM 		} else {
262*7887SLiane.Praza@Sun.COM 			assert(0);
263*7887SLiane.Praza@Sun.COM 			abort();
264*7887SLiane.Praza@Sun.COM 		}
265*7887SLiane.Praza@Sun.COM 	}
266*7887SLiane.Praza@Sun.COM 
267*7887SLiane.Praza@Sun.COM 	return (buf);
268*7887SLiane.Praza@Sun.COM }
269*7887SLiane.Praza@Sun.COM 
270*7887SLiane.Praza@Sun.COM /*
271*7887SLiane.Praza@Sun.COM  * char *_scf_get_prop_type()
272*7887SLiane.Praza@Sun.COM  *
273*7887SLiane.Praza@Sun.COM  * Given a property, returns the type in an allocated string.  The string must
274*7887SLiane.Praza@Sun.COM  * be freed with free().
275*7887SLiane.Praza@Sun.COM  *
276*7887SLiane.Praza@Sun.COM  * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
277*7887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
278*7887SLiane.Praza@Sun.COM  */
279*7887SLiane.Praza@Sun.COM static char *
280*7887SLiane.Praza@Sun.COM _scf_get_prop_type(scf_property_t *prop)
281*7887SLiane.Praza@Sun.COM {
282*7887SLiane.Praza@Sun.COM 	scf_type_t type;
283*7887SLiane.Praza@Sun.COM 	char *ret;
284*7887SLiane.Praza@Sun.COM 
285*7887SLiane.Praza@Sun.COM 	if (scf_property_type(prop, &type) == -1) {
286*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
287*7887SLiane.Praza@Sun.COM 			return (NULL);
288*7887SLiane.Praza@Sun.COM 		} else {
289*7887SLiane.Praza@Sun.COM 			assert(0);
290*7887SLiane.Praza@Sun.COM 			abort();
291*7887SLiane.Praza@Sun.COM 		}
292*7887SLiane.Praza@Sun.COM 	}
293*7887SLiane.Praza@Sun.COM 
294*7887SLiane.Praza@Sun.COM 	ret = strdup(scf_type_to_string(type));
295*7887SLiane.Praza@Sun.COM 	if (ret == NULL)
296*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
297*7887SLiane.Praza@Sun.COM 
298*7887SLiane.Praza@Sun.COM 	return (ret);
299*7887SLiane.Praza@Sun.COM }
300*7887SLiane.Praza@Sun.COM 
301*7887SLiane.Praza@Sun.COM /*
302*7887SLiane.Praza@Sun.COM  * int _read_single_value_from_pg()
303*7887SLiane.Praza@Sun.COM  *
304*7887SLiane.Praza@Sun.COM  * Reads a single value from the pg and property name specified.  On success,
305*7887SLiane.Praza@Sun.COM  * returns an allocated value that must be freed.
306*7887SLiane.Praza@Sun.COM  *
307*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
308*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_BACKEND_ACCESS
309*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_CONNECTION_BROKEN
310*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_CONSTRAINT_VIOLATED
311*7887SLiane.Praza@Sun.COM  *    Property has more than one value associated with it.
312*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_DELETED
313*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_HANDLE_DESTROYED
314*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_INTERNAL
315*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_INVALID_ARGUMENT
316*7887SLiane.Praza@Sun.COM  *    prop_name not a valid property name.
317*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_NO_MEMORY
318*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_NO_RESOURCES
319*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_NOT_BOUND
320*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_NOT_FOUND
321*7887SLiane.Praza@Sun.COM  *    Property doesn't exist or exists and has no value.
322*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_NOT_SET
323*7887SLiane.Praza@Sun.COM  *    Property group specified by pg is not set.
324*7887SLiane.Praza@Sun.COM  *  SCF_ERROR_PERMISSION_DENIED
325*7887SLiane.Praza@Sun.COM  */
326*7887SLiane.Praza@Sun.COM static int
327*7887SLiane.Praza@Sun.COM _read_single_value_from_pg(scf_propertygroup_t *pg, const char *prop_name,
328*7887SLiane.Praza@Sun.COM     scf_value_t **val)
329*7887SLiane.Praza@Sun.COM {
330*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
331*7887SLiane.Praza@Sun.COM 	scf_property_t *prop;
332*7887SLiane.Praza@Sun.COM 	int ret = 0;
333*7887SLiane.Praza@Sun.COM 
334*7887SLiane.Praza@Sun.COM 	assert(val != NULL);
335*7887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
336*7887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
337*7887SLiane.Praza@Sun.COM 		return (-1);
338*7887SLiane.Praza@Sun.COM 	}
339*7887SLiane.Praza@Sun.COM 
340*7887SLiane.Praza@Sun.COM 	prop = scf_property_create(h);
341*7887SLiane.Praza@Sun.COM 	*val = scf_value_create(h);
342*7887SLiane.Praza@Sun.COM 
343*7887SLiane.Praza@Sun.COM 	if (prop == NULL || *val == NULL) {
344*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
345*7887SLiane.Praza@Sun.COM 		goto read_single_value_from_pg_fail;
346*7887SLiane.Praza@Sun.COM 	}
347*7887SLiane.Praza@Sun.COM 
348*7887SLiane.Praza@Sun.COM 	if (scf_pg_get_property(pg, prop_name, prop) != 0) {
349*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
350*7887SLiane.Praza@Sun.COM 		goto read_single_value_from_pg_fail;
351*7887SLiane.Praza@Sun.COM 	}
352*7887SLiane.Praza@Sun.COM 
353*7887SLiane.Praza@Sun.COM 	if (scf_property_get_value(prop, *val) == -1) {
354*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
355*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
356*7887SLiane.Praza@Sun.COM 		goto read_single_value_from_pg_fail;
357*7887SLiane.Praza@Sun.COM 	}
358*7887SLiane.Praza@Sun.COM 
359*7887SLiane.Praza@Sun.COM 	goto read_single_value_from_pg_done;
360*7887SLiane.Praza@Sun.COM 
361*7887SLiane.Praza@Sun.COM read_single_value_from_pg_fail:
362*7887SLiane.Praza@Sun.COM 	scf_value_destroy(*val);
363*7887SLiane.Praza@Sun.COM 	*val = NULL;
364*7887SLiane.Praza@Sun.COM 	ret = -1;
365*7887SLiane.Praza@Sun.COM 
366*7887SLiane.Praza@Sun.COM read_single_value_from_pg_done:
367*7887SLiane.Praza@Sun.COM 	scf_property_destroy(prop);
368*7887SLiane.Praza@Sun.COM 	return (ret);
369*7887SLiane.Praza@Sun.COM }
370*7887SLiane.Praza@Sun.COM 
371*7887SLiane.Praza@Sun.COM /*
372*7887SLiane.Praza@Sun.COM  * char *_scf_read_single_astring_from_pg()
373*7887SLiane.Praza@Sun.COM  *
374*7887SLiane.Praza@Sun.COM  * Reads an astring from the pg and property name specified.  On success,
375*7887SLiane.Praza@Sun.COM  * returns an allocated string.  The string must be freed with free().
376*7887SLiane.Praza@Sun.COM  *
377*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
378*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
379*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
380*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
381*7887SLiane.Praza@Sun.COM  *     Property has more than one value associated with it.
382*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
383*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
384*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
385*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
386*7887SLiane.Praza@Sun.COM  *     prop_name not a valid property name.
387*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
388*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
389*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
390*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
391*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
392*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
393*7887SLiane.Praza@Sun.COM  *     The property group specified by pg is not set.
394*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
395*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
396*7887SLiane.Praza@Sun.COM  */
397*7887SLiane.Praza@Sun.COM char *
398*7887SLiane.Praza@Sun.COM _scf_read_single_astring_from_pg(scf_propertygroup_t *pg, const char *prop_name)
399*7887SLiane.Praza@Sun.COM {
400*7887SLiane.Praza@Sun.COM 	scf_value_t *val;
401*7887SLiane.Praza@Sun.COM 	char *ret = NULL;
402*7887SLiane.Praza@Sun.COM 	ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
403*7887SLiane.Praza@Sun.COM 
404*7887SLiane.Praza@Sun.COM 	assert(rsize != 0);
405*7887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(pg, prop_name, &val) == -1)
406*7887SLiane.Praza@Sun.COM 		return (NULL);
407*7887SLiane.Praza@Sun.COM 
408*7887SLiane.Praza@Sun.COM 	ret = malloc(rsize);
409*7887SLiane.Praza@Sun.COM 	if (ret == NULL) {
410*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
411*7887SLiane.Praza@Sun.COM 		goto cleanup;
412*7887SLiane.Praza@Sun.COM 	}
413*7887SLiane.Praza@Sun.COM 
414*7887SLiane.Praza@Sun.COM 	if (scf_value_get_astring(val, ret, rsize) < 0) {
415*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
416*7887SLiane.Praza@Sun.COM 		free(ret);
417*7887SLiane.Praza@Sun.COM 		ret = NULL;
418*7887SLiane.Praza@Sun.COM 	}
419*7887SLiane.Praza@Sun.COM 
420*7887SLiane.Praza@Sun.COM cleanup:
421*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
422*7887SLiane.Praza@Sun.COM 	return (ret);
423*7887SLiane.Praza@Sun.COM }
424*7887SLiane.Praza@Sun.COM 
425*7887SLiane.Praza@Sun.COM /*
426*7887SLiane.Praza@Sun.COM  * char *_scf_read_tmpl_prop_type_as_string()
427*7887SLiane.Praza@Sun.COM  *
428*7887SLiane.Praza@Sun.COM  * Reads the property type and returns it as an allocated string.  The string
429*7887SLiane.Praza@Sun.COM  * must be freed with free().
430*7887SLiane.Praza@Sun.COM  *
431*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _BACKEND_ACCESS,
432*7887SLiane.Praza@Sun.COM  * _CONNECTION_BROKEN, _DELETED, _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY,
433*7887SLiane.Praza@Sun.COM  * _NO_RESOURCES, _NOT_BOUND, _PERMISSION_DENIED, or _TEMPLATE_INVALID.
434*7887SLiane.Praza@Sun.COM  */
435*7887SLiane.Praza@Sun.COM char *
436*7887SLiane.Praza@Sun.COM _scf_read_tmpl_prop_type_as_string(const scf_prop_tmpl_t *pt)
437*7887SLiane.Praza@Sun.COM {
438*7887SLiane.Praza@Sun.COM 	char *type;
439*7887SLiane.Praza@Sun.COM 
440*7887SLiane.Praza@Sun.COM 	type = _scf_read_single_astring_from_pg(pt->prt_pg,
441*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TYPE);
442*7887SLiane.Praza@Sun.COM 	if (type == NULL) {
443*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
444*7887SLiane.Praza@Sun.COM 			return (NULL);
445*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
446*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
447*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
448*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
449*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
450*7887SLiane.Praza@Sun.COM 			return (NULL);
451*7887SLiane.Praza@Sun.COM 
452*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
453*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
454*7887SLiane.Praza@Sun.COM 		default:
455*7887SLiane.Praza@Sun.COM 			assert(0);
456*7887SLiane.Praza@Sun.COM 			abort();
457*7887SLiane.Praza@Sun.COM 		}
458*7887SLiane.Praza@Sun.COM 	}
459*7887SLiane.Praza@Sun.COM 
460*7887SLiane.Praza@Sun.COM 	return (type);
461*7887SLiane.Praza@Sun.COM }
462*7887SLiane.Praza@Sun.COM 
463*7887SLiane.Praza@Sun.COM /*
464*7887SLiane.Praza@Sun.COM  * int _read_single_boolean_from_pg()
465*7887SLiane.Praza@Sun.COM  *
466*7887SLiane.Praza@Sun.COM  * Reads a boolean from the pg and property name specified.
467*7887SLiane.Praza@Sun.COM  *
468*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
469*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
470*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
471*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
472*7887SLiane.Praza@Sun.COM  *     Property has more than one value associated with it.
473*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
474*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
475*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
476*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
477*7887SLiane.Praza@Sun.COM  *     prop_name is not a valid property name.
478*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
479*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
480*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
481*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
482*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
483*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
484*7887SLiane.Praza@Sun.COM  *     The property group specified by pg is not set.
485*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
486*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
487*7887SLiane.Praza@Sun.COM  */
488*7887SLiane.Praza@Sun.COM static int
489*7887SLiane.Praza@Sun.COM _read_single_boolean_from_pg(scf_propertygroup_t *pg, const char *prop_name,
490*7887SLiane.Praza@Sun.COM     uint8_t *bool)
491*7887SLiane.Praza@Sun.COM {
492*7887SLiane.Praza@Sun.COM 	scf_value_t *val;
493*7887SLiane.Praza@Sun.COM 	int ret = 0;
494*7887SLiane.Praza@Sun.COM 
495*7887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(pg, prop_name, &val) == -1)
496*7887SLiane.Praza@Sun.COM 		return (-1);
497*7887SLiane.Praza@Sun.COM 
498*7887SLiane.Praza@Sun.COM 	if (scf_value_get_boolean(val, bool) < 0) {
499*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
500*7887SLiane.Praza@Sun.COM 		ret = -1;
501*7887SLiane.Praza@Sun.COM 	}
502*7887SLiane.Praza@Sun.COM 
503*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
504*7887SLiane.Praza@Sun.COM 	return (ret);
505*7887SLiane.Praza@Sun.COM }
506*7887SLiane.Praza@Sun.COM 
507*7887SLiane.Praza@Sun.COM /*
508*7887SLiane.Praza@Sun.COM  * char **_append_astrings_values()
509*7887SLiane.Praza@Sun.COM  *
510*7887SLiane.Praza@Sun.COM  * This function reads the values from the property prop_name in pg and
511*7887SLiane.Praza@Sun.COM  * appends to an existing scf_values_t *vals.  vals may be empty, but
512*7887SLiane.Praza@Sun.COM  * must exist.  The function skips over zero-length and duplicate values.
513*7887SLiane.Praza@Sun.COM  *
514*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
515*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
516*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
517*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
518*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
519*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
520*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
521*7887SLiane.Praza@Sun.COM  *     prop_name is not a valid property name.
522*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
523*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
524*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
525*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
526*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
527*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
528*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
529*7887SLiane.Praza@Sun.COM  */
530*7887SLiane.Praza@Sun.COM static char **
531*7887SLiane.Praza@Sun.COM _append_astrings_values(scf_propertygroup_t *pg, const char *prop_name,
532*7887SLiane.Praza@Sun.COM     scf_values_t *vals)
533*7887SLiane.Praza@Sun.COM {
534*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
535*7887SLiane.Praza@Sun.COM 	scf_property_t *prop;
536*7887SLiane.Praza@Sun.COM 	scf_value_t *val;
537*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter;
538*7887SLiane.Praza@Sun.COM 	ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
539*7887SLiane.Praza@Sun.COM 	int err, count, cursz, i;
540*7887SLiane.Praza@Sun.COM 
541*7887SLiane.Praza@Sun.COM 	assert(vals != NULL);
542*7887SLiane.Praza@Sun.COM 	assert(vals->value_type == SCF_TYPE_ASTRING);
543*7887SLiane.Praza@Sun.COM 	assert(vals->reserved == NULL);
544*7887SLiane.Praza@Sun.COM 	count = vals->value_count;
545*7887SLiane.Praza@Sun.COM 	if (count == 0) {
546*7887SLiane.Praza@Sun.COM 		cursz = 8;
547*7887SLiane.Praza@Sun.COM 		vals->values.v_astring = calloc(cursz, sizeof (char *));
548*7887SLiane.Praza@Sun.COM 		if (vals->values.v_astring == NULL) {
549*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
550*7887SLiane.Praza@Sun.COM 			return (NULL);
551*7887SLiane.Praza@Sun.COM 		}
552*7887SLiane.Praza@Sun.COM 	} else {
553*7887SLiane.Praza@Sun.COM 		/*
554*7887SLiane.Praza@Sun.COM 		 * The array may be bigger, but it is irrelevant since
555*7887SLiane.Praza@Sun.COM 		 * we will always re-allocate a new one.
556*7887SLiane.Praza@Sun.COM 		 */
557*7887SLiane.Praza@Sun.COM 		cursz = count;
558*7887SLiane.Praza@Sun.COM 	}
559*7887SLiane.Praza@Sun.COM 
560*7887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
561*7887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
562*7887SLiane.Praza@Sun.COM 		return (NULL);
563*7887SLiane.Praza@Sun.COM 	}
564*7887SLiane.Praza@Sun.COM 
565*7887SLiane.Praza@Sun.COM 	prop = scf_property_create(h);
566*7887SLiane.Praza@Sun.COM 	val = scf_value_create(h);
567*7887SLiane.Praza@Sun.COM 	iter = scf_iter_create(h);
568*7887SLiane.Praza@Sun.COM 
569*7887SLiane.Praza@Sun.COM 	if (prop == NULL || val == NULL || iter == NULL) {
570*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
571*7887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
572*7887SLiane.Praza@Sun.COM 	}
573*7887SLiane.Praza@Sun.COM 
574*7887SLiane.Praza@Sun.COM 	if (scf_pg_get_property(pg, prop_name, prop) != 0) {
575*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
576*7887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
577*7887SLiane.Praza@Sun.COM 	}
578*7887SLiane.Praza@Sun.COM 
579*7887SLiane.Praza@Sun.COM 	if (scf_iter_property_values(iter, prop) != 0) {
580*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
581*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
582*7887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
583*7887SLiane.Praza@Sun.COM 	}
584*7887SLiane.Praza@Sun.COM 
585*7887SLiane.Praza@Sun.COM 	while ((err = scf_iter_next_value(iter, val)) == 1) {
586*7887SLiane.Praza@Sun.COM 		int flag;
587*7887SLiane.Praza@Sun.COM 		int r;
588*7887SLiane.Praza@Sun.COM 
589*7887SLiane.Praza@Sun.COM 		if (count + 1 >= cursz) {
590*7887SLiane.Praza@Sun.COM 			void *aux;
591*7887SLiane.Praza@Sun.COM 
592*7887SLiane.Praza@Sun.COM 			cursz *= 2;
593*7887SLiane.Praza@Sun.COM 			if ((aux = calloc(cursz, sizeof (char *))) == NULL) {
594*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
595*7887SLiane.Praza@Sun.COM 				goto append_single_astring_from_pg_fail;
596*7887SLiane.Praza@Sun.COM 			}
597*7887SLiane.Praza@Sun.COM 			(void) memcpy(aux, vals->values.v_astring,
598*7887SLiane.Praza@Sun.COM 			    count * sizeof (char *));
599*7887SLiane.Praza@Sun.COM 			free(vals->values.v_astring);
600*7887SLiane.Praza@Sun.COM 			vals->values.v_astring = aux;
601*7887SLiane.Praza@Sun.COM 		}
602*7887SLiane.Praza@Sun.COM 
603*7887SLiane.Praza@Sun.COM 		vals->values.v_astring[count] = malloc(rsize);
604*7887SLiane.Praza@Sun.COM 		if (vals->values.v_astring[count] == NULL) {
605*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
606*7887SLiane.Praza@Sun.COM 			goto append_single_astring_from_pg_fail;
607*7887SLiane.Praza@Sun.COM 		}
608*7887SLiane.Praza@Sun.COM 
609*7887SLiane.Praza@Sun.COM 		if ((r = scf_value_get_astring(val,
610*7887SLiane.Praza@Sun.COM 		    vals->values.v_astring[count], rsize)) <= 0) {
611*7887SLiane.Praza@Sun.COM 			/* discard zero length strings */
612*7887SLiane.Praza@Sun.COM 			if (r == 0) {
613*7887SLiane.Praza@Sun.COM 				free(vals->values.v_astring[count]);
614*7887SLiane.Praza@Sun.COM 				continue;
615*7887SLiane.Praza@Sun.COM 			}
616*7887SLiane.Praza@Sun.COM 			assert(scf_error() != SCF_ERROR_NOT_SET);
617*7887SLiane.Praza@Sun.COM 			goto append_single_astring_from_pg_fail;
618*7887SLiane.Praza@Sun.COM 		}
619*7887SLiane.Praza@Sun.COM 		for (i = 0, flag = 0; i < count; ++i) {
620*7887SLiane.Praza@Sun.COM 			/* find  and discard duplicates */
621*7887SLiane.Praza@Sun.COM 			if (strncmp(vals->values.v_astring[i],
622*7887SLiane.Praza@Sun.COM 			    vals->values.v_astring[count], rsize) == 0) {
623*7887SLiane.Praza@Sun.COM 				free(vals->values.v_astring[count]);
624*7887SLiane.Praza@Sun.COM 				flag = 1;
625*7887SLiane.Praza@Sun.COM 				break;
626*7887SLiane.Praza@Sun.COM 			}
627*7887SLiane.Praza@Sun.COM 		}
628*7887SLiane.Praza@Sun.COM 		if (flag == 1)
629*7887SLiane.Praza@Sun.COM 			continue;
630*7887SLiane.Praza@Sun.COM 
631*7887SLiane.Praza@Sun.COM 		count++;
632*7887SLiane.Praza@Sun.COM 	}
633*7887SLiane.Praza@Sun.COM 
634*7887SLiane.Praza@Sun.COM 	vals->value_count = count;
635*7887SLiane.Praza@Sun.COM 
636*7887SLiane.Praza@Sun.COM 	if (err != 0) {
637*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
638*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
639*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH);
640*7887SLiane.Praza@Sun.COM 		goto append_single_astring_from_pg_fail;
641*7887SLiane.Praza@Sun.COM 	} else {
642*7887SLiane.Praza@Sun.COM 		vals->values_as_strings = vals->values.v_astring;
643*7887SLiane.Praza@Sun.COM 	}
644*7887SLiane.Praza@Sun.COM 
645*7887SLiane.Praza@Sun.COM 	goto append_single_astring_from_pg_done;
646*7887SLiane.Praza@Sun.COM 
647*7887SLiane.Praza@Sun.COM append_single_astring_from_pg_fail:
648*7887SLiane.Praza@Sun.COM 	for (i = 0; i <= count; ++i) {
649*7887SLiane.Praza@Sun.COM 		if (vals->values.v_astring[i] != NULL)
650*7887SLiane.Praza@Sun.COM 			free(vals->values.v_astring[i]);
651*7887SLiane.Praza@Sun.COM 		vals->values.v_astring[i] = NULL;
652*7887SLiane.Praza@Sun.COM 	}
653*7887SLiane.Praza@Sun.COM 	free(vals->values.v_astring);
654*7887SLiane.Praza@Sun.COM 	vals->values.v_astring = NULL;
655*7887SLiane.Praza@Sun.COM 	vals->value_count = 0;
656*7887SLiane.Praza@Sun.COM 
657*7887SLiane.Praza@Sun.COM append_single_astring_from_pg_done:
658*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
659*7887SLiane.Praza@Sun.COM 	scf_property_destroy(prop);
660*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
661*7887SLiane.Praza@Sun.COM 	return (vals->values.v_astring);
662*7887SLiane.Praza@Sun.COM }
663*7887SLiane.Praza@Sun.COM 
664*7887SLiane.Praza@Sun.COM /*
665*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
666*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
667*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
668*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
669*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
670*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
671*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
672*7887SLiane.Praza@Sun.COM  *     prop_name is not a valid property name.
673*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
674*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
675*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
676*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
677*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
678*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
679*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
680*7887SLiane.Praza@Sun.COM  */
681*7887SLiane.Praza@Sun.COM static char **
682*7887SLiane.Praza@Sun.COM _read_astrings_values(scf_propertygroup_t *pg, const char *prop_name,
683*7887SLiane.Praza@Sun.COM     scf_values_t *vals)
684*7887SLiane.Praza@Sun.COM {
685*7887SLiane.Praza@Sun.COM 	assert(vals != NULL);
686*7887SLiane.Praza@Sun.COM 	vals->value_count = 0;
687*7887SLiane.Praza@Sun.COM 	vals->value_type = SCF_TYPE_ASTRING;
688*7887SLiane.Praza@Sun.COM 	vals->reserved = NULL;
689*7887SLiane.Praza@Sun.COM 	return (_append_astrings_values(pg, prop_name, vals));
690*7887SLiane.Praza@Sun.COM }
691*7887SLiane.Praza@Sun.COM 
692*7887SLiane.Praza@Sun.COM void
693*7887SLiane.Praza@Sun.COM _scf_sanitize_locale(char *locale)
694*7887SLiane.Praza@Sun.COM {
695*7887SLiane.Praza@Sun.COM 	for (; *locale != '\0'; locale++)
696*7887SLiane.Praza@Sun.COM 		if (!isalnum(*locale) && *locale != '_')
697*7887SLiane.Praza@Sun.COM 			*locale = '_';
698*7887SLiane.Praza@Sun.COM }
699*7887SLiane.Praza@Sun.COM 
700*7887SLiane.Praza@Sun.COM /*
701*7887SLiane.Praza@Sun.COM  * The returned string needs to be freed by the caller
702*7887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error() to:
703*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
704*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
705*7887SLiane.Praza@Sun.COM  *     Name isn't short enough to add the locale to.
706*7887SLiane.Praza@Sun.COM  */
707*7887SLiane.Praza@Sun.COM static char *
708*7887SLiane.Praza@Sun.COM _add_locale_to_name(const char *name, const char *locale)
709*7887SLiane.Praza@Sun.COM {
710*7887SLiane.Praza@Sun.COM 	char *lname = NULL;
711*7887SLiane.Praza@Sun.COM 	ssize_t lsz;
712*7887SLiane.Praza@Sun.COM 	char *loc;
713*7887SLiane.Praza@Sun.COM 
714*7887SLiane.Praza@Sun.COM 	if (locale == NULL)
715*7887SLiane.Praza@Sun.COM 		locale = setlocale(LC_MESSAGES, NULL);
716*7887SLiane.Praza@Sun.COM 	loc = strdup(locale);
717*7887SLiane.Praza@Sun.COM 	if (loc == NULL) {
718*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
719*7887SLiane.Praza@Sun.COM 		return (NULL);
720*7887SLiane.Praza@Sun.COM 	} else {
721*7887SLiane.Praza@Sun.COM 		_scf_sanitize_locale(loc);
722*7887SLiane.Praza@Sun.COM 	}
723*7887SLiane.Praza@Sun.COM 
724*7887SLiane.Praza@Sun.COM 	lsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
725*7887SLiane.Praza@Sun.COM 	lname = malloc(lsz);
726*7887SLiane.Praza@Sun.COM 	if (lname == NULL) {
727*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
728*7887SLiane.Praza@Sun.COM 		goto cleanup;
729*7887SLiane.Praza@Sun.COM 	}
730*7887SLiane.Praza@Sun.COM 
731*7887SLiane.Praza@Sun.COM 	(void) strlcpy(lname, name, lsz);
732*7887SLiane.Praza@Sun.COM 	if (strlcat(lname, loc, lsz) >= lsz) {
733*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
734*7887SLiane.Praza@Sun.COM 		free(lname);
735*7887SLiane.Praza@Sun.COM 		lname = NULL;
736*7887SLiane.Praza@Sun.COM 	}
737*7887SLiane.Praza@Sun.COM cleanup:
738*7887SLiane.Praza@Sun.COM 	free(loc);
739*7887SLiane.Praza@Sun.COM 
740*7887SLiane.Praza@Sun.COM 	return (lname);
741*7887SLiane.Praza@Sun.COM }
742*7887SLiane.Praza@Sun.COM 
743*7887SLiane.Praza@Sun.COM /*
744*7887SLiane.Praza@Sun.COM  * char *_tmpl_pg_name(pg, type, use_type)
745*7887SLiane.Praza@Sun.COM  *
746*7887SLiane.Praza@Sun.COM  * pg and type can both be NULL.  Returns the name of the most specific
747*7887SLiane.Praza@Sun.COM  * template property group name based on the inputs.
748*7887SLiane.Praza@Sun.COM  * If use_type is set and pg is not NULL, a property group name for a
749*7887SLiane.Praza@Sun.COM  * property group template that has type defined is returned, even if no
750*7887SLiane.Praza@Sun.COM  * type is provided.
751*7887SLiane.Praza@Sun.COM  *
752*7887SLiane.Praza@Sun.COM  * Returns NULL on failure and sets scf_error() to:
753*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
754*7887SLiane.Praza@Sun.COM  *     can't combine the arguments and get a reasonable length name
755*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
756*7887SLiane.Praza@Sun.COM  *
757*7887SLiane.Praza@Sun.COM  */
758*7887SLiane.Praza@Sun.COM static char *
759*7887SLiane.Praza@Sun.COM _tmpl_pg_name(const char *pg, const char *type, int use_type)
760*7887SLiane.Praza@Sun.COM {
761*7887SLiane.Praza@Sun.COM 	char *name;
762*7887SLiane.Praza@Sun.COM 	ssize_t limit, size = 0;
763*7887SLiane.Praza@Sun.COM 
764*7887SLiane.Praza@Sun.COM 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
765*7887SLiane.Praza@Sun.COM 	name = malloc(limit);
766*7887SLiane.Praza@Sun.COM 	if (name == NULL) {
767*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
768*7887SLiane.Praza@Sun.COM 		return (NULL);
769*7887SLiane.Praza@Sun.COM 	}
770*7887SLiane.Praza@Sun.COM 
771*7887SLiane.Praza@Sun.COM 	if (pg == NULL && type == NULL) {
772*7887SLiane.Praza@Sun.COM 		if (strlcpy(name, SCF_PG_TM_PG_PATTERN_PREFIX, limit) >=
773*7887SLiane.Praza@Sun.COM 		    limit) {
774*7887SLiane.Praza@Sun.COM 			assert(0);
775*7887SLiane.Praza@Sun.COM 			abort();
776*7887SLiane.Praza@Sun.COM 		}
777*7887SLiane.Praza@Sun.COM 		return (name);
778*7887SLiane.Praza@Sun.COM 	} else if (pg != NULL && type != NULL) {
779*7887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
780*7887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg);
781*7887SLiane.Praza@Sun.COM 	} else if (pg != NULL && type == NULL && use_type == 1) {
782*7887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
783*7887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg);
784*7887SLiane.Praza@Sun.COM 	} else if (pg != NULL && type == NULL) {
785*7887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
786*7887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_N_PREFIX, pg);
787*7887SLiane.Praza@Sun.COM 	} else if (type != NULL && pg == NULL) {
788*7887SLiane.Praza@Sun.COM 		size = snprintf(name, limit, "%s%s",
789*7887SLiane.Praza@Sun.COM 		    SCF_PG_TM_PG_PATTERN_T_PREFIX, type);
790*7887SLiane.Praza@Sun.COM 	} else {
791*7887SLiane.Praza@Sun.COM 		assert(0);
792*7887SLiane.Praza@Sun.COM 		abort();
793*7887SLiane.Praza@Sun.COM 	}
794*7887SLiane.Praza@Sun.COM 
795*7887SLiane.Praza@Sun.COM 	if (size >= limit) {
796*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
797*7887SLiane.Praza@Sun.COM 		free(name);
798*7887SLiane.Praza@Sun.COM 		return (NULL);
799*7887SLiane.Praza@Sun.COM 	} else {
800*7887SLiane.Praza@Sun.COM 		return (name);
801*7887SLiane.Praza@Sun.COM 	}
802*7887SLiane.Praza@Sun.COM }
803*7887SLiane.Praza@Sun.COM 
804*7887SLiane.Praza@Sun.COM /*
805*7887SLiane.Praza@Sun.COM  * _scf_get_pg_name()
806*7887SLiane.Praza@Sun.COM  * Gets the name of the supplied property group.  On success, returns an
807*7887SLiane.Praza@Sun.COM  * allocated string.  The string must be freed by free().
808*7887SLiane.Praza@Sun.COM  *
809*7887SLiane.Praza@Sun.COM  * Returns NULL on failure and sets scf_error() to _CONNECTION_BROKEN,
810*7887SLiane.Praza@Sun.COM  * _DELETED, or _NO_MEMORY.
811*7887SLiane.Praza@Sun.COM  */
812*7887SLiane.Praza@Sun.COM static char *
813*7887SLiane.Praza@Sun.COM _scf_get_pg_name(scf_propertygroup_t *pg)
814*7887SLiane.Praza@Sun.COM {
815*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
816*7887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
817*7887SLiane.Praza@Sun.COM 
818*7887SLiane.Praza@Sun.COM 	if (buf == NULL) {
819*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
820*7887SLiane.Praza@Sun.COM 	} else if (scf_pg_get_name(pg, buf, sz) == -1) {
821*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
822*7887SLiane.Praza@Sun.COM 			free(buf);
823*7887SLiane.Praza@Sun.COM 			buf = NULL;
824*7887SLiane.Praza@Sun.COM 		} else {
825*7887SLiane.Praza@Sun.COM 			assert(0);
826*7887SLiane.Praza@Sun.COM 			abort();
827*7887SLiane.Praza@Sun.COM 		}
828*7887SLiane.Praza@Sun.COM 	}
829*7887SLiane.Praza@Sun.COM 
830*7887SLiane.Praza@Sun.COM 	return (buf);
831*7887SLiane.Praza@Sun.COM }
832*7887SLiane.Praza@Sun.COM 
833*7887SLiane.Praza@Sun.COM /*
834*7887SLiane.Praza@Sun.COM  * char *_tmpl_prop_name()
835*7887SLiane.Praza@Sun.COM  *
836*7887SLiane.Praza@Sun.COM  * Returns the name of the property template prop (which is the name of
837*7887SLiane.Praza@Sun.COM  * the property template property group) in the property group
838*7887SLiane.Praza@Sun.COM  * template t. Returns NULL on failure and sets scf_error() to:
839*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
840*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
841*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
842*7887SLiane.Praza@Sun.COM  *     can't combine the arguments and get a reasonable length name
843*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
844*7887SLiane.Praza@Sun.COM  */
845*7887SLiane.Praza@Sun.COM static char *
846*7887SLiane.Praza@Sun.COM _tmpl_prop_name(const char *prop, scf_pg_tmpl_t *t)
847*7887SLiane.Praza@Sun.COM {
848*7887SLiane.Praza@Sun.COM 	char *name = NULL, *pg_name = NULL;
849*7887SLiane.Praza@Sun.COM 	size_t prefix_size;
850*7887SLiane.Praza@Sun.COM 	ssize_t limit, size = 0;
851*7887SLiane.Praza@Sun.COM 
852*7887SLiane.Praza@Sun.COM 	assert(prop != NULL);
853*7887SLiane.Praza@Sun.COM 	assert(t->pt_pg != NULL);
854*7887SLiane.Praza@Sun.COM 
855*7887SLiane.Praza@Sun.COM 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
856*7887SLiane.Praza@Sun.COM 	name = malloc(limit);
857*7887SLiane.Praza@Sun.COM 	if (name == NULL) {
858*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
859*7887SLiane.Praza@Sun.COM 		return (NULL);
860*7887SLiane.Praza@Sun.COM 	}
861*7887SLiane.Praza@Sun.COM 
862*7887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(t->pt_pg)) == NULL) {
863*7887SLiane.Praza@Sun.COM 		free(name);
864*7887SLiane.Praza@Sun.COM 		return (NULL);
865*7887SLiane.Praza@Sun.COM 	}
866*7887SLiane.Praza@Sun.COM 
867*7887SLiane.Praza@Sun.COM 	prefix_size = strlen(SCF_PG_TM_PG_PAT_BASE);
868*7887SLiane.Praza@Sun.COM 	if (strncmp(pg_name, SCF_PG_TM_PG_PAT_BASE, prefix_size) != 0) {
869*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
870*7887SLiane.Praza@Sun.COM 		free(name);
871*7887SLiane.Praza@Sun.COM 		free(pg_name);
872*7887SLiane.Praza@Sun.COM 		return (NULL);
873*7887SLiane.Praza@Sun.COM 	}
874*7887SLiane.Praza@Sun.COM 
875*7887SLiane.Praza@Sun.COM 	size = snprintf(name, limit, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX,
876*7887SLiane.Praza@Sun.COM 	    pg_name + prefix_size, prop);
877*7887SLiane.Praza@Sun.COM 
878*7887SLiane.Praza@Sun.COM 	if (size >= limit) {
879*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
880*7887SLiane.Praza@Sun.COM 		free(name);
881*7887SLiane.Praza@Sun.COM 		free(pg_name);
882*7887SLiane.Praza@Sun.COM 		return (NULL);
883*7887SLiane.Praza@Sun.COM 	} else {
884*7887SLiane.Praza@Sun.COM 		free(pg_name);
885*7887SLiane.Praza@Sun.COM 		return (name);
886*7887SLiane.Praza@Sun.COM 	}
887*7887SLiane.Praza@Sun.COM }
888*7887SLiane.Praza@Sun.COM 
889*7887SLiane.Praza@Sun.COM /*
890*7887SLiane.Praza@Sun.COM  *  int _get_snapshot()
891*7887SLiane.Praza@Sun.COM  *
892*7887SLiane.Praza@Sun.COM  *  Gets the specified snapshot.  If "snapshot" isn't defined, use the
893*7887SLiane.Praza@Sun.COM  *  running snapshot.  If the snapshot isn't found, that may or may
894*7887SLiane.Praza@Sun.COM  *  not be an error depending on the caller.  Return 0 in that case,
895*7887SLiane.Praza@Sun.COM  *  but leave scf_error() set to SCF_ERROR_NOT_FOUND.  On all other
896*7887SLiane.Praza@Sun.COM  *  errors, set scf_error() to:
897*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
898*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
899*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
900*7887SLiane.Praza@Sun.COM  *   SCF_ERR_HANDLE_DESTROYED
901*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
902*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
903*7887SLiane.Praza@Sun.COM  *     The handle argument is NULL, or snaphot is not a valid snapshot name
904*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
905*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
906*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
907*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
908*7887SLiane.Praza@Sun.COM  */
909*7887SLiane.Praza@Sun.COM static int
910*7887SLiane.Praza@Sun.COM _get_snapshot(scf_instance_t *inst, const char *snapshot,
911*7887SLiane.Praza@Sun.COM     scf_snapshot_t **snap)
912*7887SLiane.Praza@Sun.COM {
913*7887SLiane.Praza@Sun.COM 	int err;
914*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
915*7887SLiane.Praza@Sun.COM 
916*7887SLiane.Praza@Sun.COM 	h = scf_instance_handle(inst);
917*7887SLiane.Praza@Sun.COM 	if (h == NULL)
918*7887SLiane.Praza@Sun.COM 		return (-1);
919*7887SLiane.Praza@Sun.COM 
920*7887SLiane.Praza@Sun.COM 	if ((*snap = scf_snapshot_create(h)) == NULL) {
921*7887SLiane.Praza@Sun.COM 		return (-1);
922*7887SLiane.Praza@Sun.COM 	}
923*7887SLiane.Praza@Sun.COM 
924*7887SLiane.Praza@Sun.COM 	/* Use running snapshot by default. */
925*7887SLiane.Praza@Sun.COM 	if (snapshot == NULL)
926*7887SLiane.Praza@Sun.COM 		err = scf_instance_get_snapshot(inst, "running", *snap);
927*7887SLiane.Praza@Sun.COM 	else
928*7887SLiane.Praza@Sun.COM 		err = scf_instance_get_snapshot(inst, snapshot, *snap);
929*7887SLiane.Praza@Sun.COM 
930*7887SLiane.Praza@Sun.COM 	if (err != 0) {
931*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
932*7887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(*snap);
933*7887SLiane.Praza@Sun.COM 			*snap = NULL;
934*7887SLiane.Praza@Sun.COM 			return (-1);
935*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
936*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
937*7887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(*snap);
938*7887SLiane.Praza@Sun.COM 			*snap = NULL;
939*7887SLiane.Praza@Sun.COM 			return (-1);
940*7887SLiane.Praza@Sun.COM 
941*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
942*7887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(*snap);
943*7887SLiane.Praza@Sun.COM 			*snap = NULL;
944*7887SLiane.Praza@Sun.COM 			return (0);
945*7887SLiane.Praza@Sun.COM 
946*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
947*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
948*7887SLiane.Praza@Sun.COM 		default:
949*7887SLiane.Praza@Sun.COM 			assert(0);
950*7887SLiane.Praza@Sun.COM 			abort();
951*7887SLiane.Praza@Sun.COM 		}
952*7887SLiane.Praza@Sun.COM 	}
953*7887SLiane.Praza@Sun.COM 
954*7887SLiane.Praza@Sun.COM 	/*
955*7887SLiane.Praza@Sun.COM 	 * Explicitly set SCF_ERROR_NONE so that the SCF_ERROR_NOT_FOUND
956*7887SLiane.Praza@Sun.COM 	 * return above is explicitly guaranteed to be from
957*7887SLiane.Praza@Sun.COM 	 * scf_instance_get_snapshot().
958*7887SLiane.Praza@Sun.COM 	 */
959*7887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NONE);
960*7887SLiane.Praza@Sun.COM 	return (0);
961*7887SLiane.Praza@Sun.COM }
962*7887SLiane.Praza@Sun.COM 
963*7887SLiane.Praza@Sun.COM /*
964*7887SLiane.Praza@Sun.COM  * Returns NULL on error, sets scf_error() to:
965*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
966*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
967*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
968*7887SLiane.Praza@Sun.COM  *     The restarter's FMRI does not match an existing instance.
969*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
970*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
971*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
972*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
973*7887SLiane.Praza@Sun.COM  *     The restarter's FMRI is not a valid FMRI.
974*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
975*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
976*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
977*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
978*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
979*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
980*7887SLiane.Praza@Sun.COM  *     restarter property is not SCF_TYPE_ASTRING or has more than one value
981*7887SLiane.Praza@Sun.COM  */
982*7887SLiane.Praza@Sun.COM static scf_instance_t *
983*7887SLiane.Praza@Sun.COM _get_restarter_inst(scf_handle_t *h, scf_service_t *svc,
984*7887SLiane.Praza@Sun.COM     scf_instance_t *inst, scf_snapshot_t *s)
985*7887SLiane.Praza@Sun.COM {
986*7887SLiane.Praza@Sun.COM 	char *restarter = NULL;
987*7887SLiane.Praza@Sun.COM 	scf_instance_t *ri = NULL;
988*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
989*7887SLiane.Praza@Sun.COM 	int ret = 0;
990*7887SLiane.Praza@Sun.COM 
991*7887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
992*7887SLiane.Praza@Sun.COM 	assert(svc ==  NULL || inst == NULL);
993*7887SLiane.Praza@Sun.COM 
994*7887SLiane.Praza@Sun.COM 	if ((ri = scf_instance_create(h)) == NULL ||
995*7887SLiane.Praza@Sun.COM 	    (pg = scf_pg_create(h)) == NULL) {
996*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
997*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(ri);
998*7887SLiane.Praza@Sun.COM 		return (NULL);
999*7887SLiane.Praza@Sun.COM 	}
1000*7887SLiane.Praza@Sun.COM 
1001*7887SLiane.Praza@Sun.COM 	if (inst != NULL)
1002*7887SLiane.Praza@Sun.COM 		ret = scf_instance_get_pg_composed(inst, s, SCF_PG_GENERAL,
1003*7887SLiane.Praza@Sun.COM 		    pg);
1004*7887SLiane.Praza@Sun.COM 	else
1005*7887SLiane.Praza@Sun.COM 		ret = scf_service_get_pg(svc, SCF_PG_GENERAL, pg);
1006*7887SLiane.Praza@Sun.COM 
1007*7887SLiane.Praza@Sun.COM 	if (ret != 0) {
1008*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
1009*7887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
1010*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
1011*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
1012*7887SLiane.Praza@Sun.COM 			/* Assume default restarter. */
1013*7887SLiane.Praza@Sun.COM 			break;
1014*7887SLiane.Praza@Sun.COM 
1015*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1016*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
1017*7887SLiane.Praza@Sun.COM 			/*
1018*7887SLiane.Praza@Sun.COM 			 * If the arguments to the above functions
1019*7887SLiane.Praza@Sun.COM 			 * aren't derived from the same handle, there's
1020*7887SLiane.Praza@Sun.COM 			 * something wrong with the internal implementation,
1021*7887SLiane.Praza@Sun.COM 			 * not the public caller further up the chain.
1022*7887SLiane.Praza@Sun.COM 			 */
1023*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
1024*7887SLiane.Praza@Sun.COM 		default:
1025*7887SLiane.Praza@Sun.COM 			assert(0);
1026*7887SLiane.Praza@Sun.COM 			abort();
1027*7887SLiane.Praza@Sun.COM 		}
1028*7887SLiane.Praza@Sun.COM 	} else {
1029*7887SLiane.Praza@Sun.COM 		restarter = _scf_read_single_astring_from_pg(pg,
1030*7887SLiane.Praza@Sun.COM 		    SCF_PROPERTY_RESTARTER);
1031*7887SLiane.Praza@Sun.COM 		/* zero length string is NOT a valid restarter */
1032*7887SLiane.Praza@Sun.COM 		if (restarter != NULL && restarter[0] == '\0') {
1033*7887SLiane.Praza@Sun.COM 			free(restarter);
1034*7887SLiane.Praza@Sun.COM 			restarter = NULL;
1035*7887SLiane.Praza@Sun.COM 		} else if (restarter == NULL) {
1036*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
1037*7887SLiane.Praza@Sun.COM 				goto _get_restarter_inst_fail;
1038*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
1039*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
1040*7887SLiane.Praza@Sun.COM 				break;
1041*7887SLiane.Praza@Sun.COM 
1042*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
1043*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_TYPE_MISMATCH:
1044*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
1045*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
1046*7887SLiane.Praza@Sun.COM 				goto _get_restarter_inst_fail;
1047*7887SLiane.Praza@Sun.COM 
1048*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
1049*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
1050*7887SLiane.Praza@Sun.COM 			default:
1051*7887SLiane.Praza@Sun.COM 				assert(0);
1052*7887SLiane.Praza@Sun.COM 				abort();
1053*7887SLiane.Praza@Sun.COM 			}
1054*7887SLiane.Praza@Sun.COM 		}
1055*7887SLiane.Praza@Sun.COM 	}
1056*7887SLiane.Praza@Sun.COM 
1057*7887SLiane.Praza@Sun.COM 	if (restarter == NULL) {
1058*7887SLiane.Praza@Sun.COM 		/* Use default restarter */
1059*7887SLiane.Praza@Sun.COM 		restarter = strdup(SCF_SERVICE_STARTD);
1060*7887SLiane.Praza@Sun.COM 		if (restarter == NULL) {
1061*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1062*7887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
1063*7887SLiane.Praza@Sun.COM 		}
1064*7887SLiane.Praza@Sun.COM 	}
1065*7887SLiane.Praza@Sun.COM 
1066*7887SLiane.Praza@Sun.COM 	if (scf_handle_decode_fmri(h, restarter, NULL, NULL, ri, NULL, NULL,
1067*7887SLiane.Praza@Sun.COM 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
1068*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
1069*7887SLiane.Praza@Sun.COM 			uu_free(restarter);
1070*7887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
1071*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
1072*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1073*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
1074*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
1075*7887SLiane.Praza@Sun.COM 			free(restarter);
1076*7887SLiane.Praza@Sun.COM 			goto _get_restarter_inst_fail;
1077*7887SLiane.Praza@Sun.COM 
1078*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
1079*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1080*7887SLiane.Praza@Sun.COM 		default:
1081*7887SLiane.Praza@Sun.COM 			assert(0);
1082*7887SLiane.Praza@Sun.COM 			abort();
1083*7887SLiane.Praza@Sun.COM 		}
1084*7887SLiane.Praza@Sun.COM 	}
1085*7887SLiane.Praza@Sun.COM 	free(restarter);
1086*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
1087*7887SLiane.Praza@Sun.COM 
1088*7887SLiane.Praza@Sun.COM 	return (ri);
1089*7887SLiane.Praza@Sun.COM 
1090*7887SLiane.Praza@Sun.COM _get_restarter_inst_fail:
1091*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(ri);
1092*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
1093*7887SLiane.Praza@Sun.COM 	return (NULL);
1094*7887SLiane.Praza@Sun.COM }
1095*7887SLiane.Praza@Sun.COM 
1096*7887SLiane.Praza@Sun.COM /*
1097*7887SLiane.Praza@Sun.COM  * Returns NULL on error, sets scf_error() to:
1098*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
1099*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
1100*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
1101*7887SLiane.Praza@Sun.COM  *     Restarter property has more than one value associated with it,
1102*7887SLiane.Praza@Sun.COM  *     or FMRI does not meet restrictions in scf_handle_decode_fmri() flags.
1103*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
1104*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
1105*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
1106*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
1107*7887SLiane.Praza@Sun.COM  *     The fmri argument in scf_handle_decode_fmri() is not a valid FMRI.
1108*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
1109*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
1110*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
1111*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
1112*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
1113*7887SLiane.Praza@Sun.COM  */
1114*7887SLiane.Praza@Sun.COM static scf_instance_t *
1115*7887SLiane.Praza@Sun.COM _get_global_inst(scf_handle_t *h)
1116*7887SLiane.Praza@Sun.COM {
1117*7887SLiane.Praza@Sun.COM 	scf_instance_t *ri;
1118*7887SLiane.Praza@Sun.COM 
1119*7887SLiane.Praza@Sun.COM 	if ((ri = scf_instance_create(h)) == NULL) {
1120*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
1121*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_RESOURCES);
1122*7887SLiane.Praza@Sun.COM 		return (NULL);
1123*7887SLiane.Praza@Sun.COM 	}
1124*7887SLiane.Praza@Sun.COM 
1125*7887SLiane.Praza@Sun.COM 	if (scf_handle_decode_fmri(h, SCF_INSTANCE_GLOBAL, NULL, NULL, ri,
1126*7887SLiane.Praza@Sun.COM 	    NULL, NULL,
1127*7887SLiane.Praza@Sun.COM 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
1128*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
1129*7887SLiane.Praza@Sun.COM 			scf_instance_destroy(ri);
1130*7887SLiane.Praza@Sun.COM 			return (NULL);
1131*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
1132*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1133*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
1134*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
1135*7887SLiane.Praza@Sun.COM 			scf_instance_destroy(ri);
1136*7887SLiane.Praza@Sun.COM 			return (NULL);
1137*7887SLiane.Praza@Sun.COM 
1138*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
1139*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1140*7887SLiane.Praza@Sun.COM 		default:
1141*7887SLiane.Praza@Sun.COM 			assert(0);
1142*7887SLiane.Praza@Sun.COM 			abort();
1143*7887SLiane.Praza@Sun.COM 		}
1144*7887SLiane.Praza@Sun.COM 	}
1145*7887SLiane.Praza@Sun.COM 
1146*7887SLiane.Praza@Sun.COM 	return (ri);
1147*7887SLiane.Praza@Sun.COM }
1148*7887SLiane.Praza@Sun.COM 
1149*7887SLiane.Praza@Sun.COM /*
1150*7887SLiane.Praza@Sun.COM  * Call the supplied function for each of the service or instance, the
1151*7887SLiane.Praza@Sun.COM  * service's restarter, and the globally defined template instance.
1152*7887SLiane.Praza@Sun.COM  * If the function returns SCF_WALK_ERROR, the walk is ended.  If
1153*7887SLiane.Praza@Sun.COM  * the function returns SCF_WALK_NEXT, the next entity is tried.
1154*7887SLiane.Praza@Sun.COM  *
1155*7887SLiane.Praza@Sun.COM  * The function is only expected to return SCF_WALK_DONE if it has
1156*7887SLiane.Praza@Sun.COM  * found a property group match in the current entity, and has
1157*7887SLiane.Praza@Sun.COM  * populated p->pw_pg with the matching property group.
1158*7887SLiane.Praza@Sun.COM  */
1159*7887SLiane.Praza@Sun.COM static void
1160*7887SLiane.Praza@Sun.COM _walk_template_instances(scf_service_t *svc, scf_instance_t *inst,
1161*7887SLiane.Praza@Sun.COM     scf_snapshot_t *snap, walk_template_inst_func_t *func,
1162*7887SLiane.Praza@Sun.COM     pg_tmpl_walk_t *p, int flag)
1163*7887SLiane.Praza@Sun.COM {
1164*7887SLiane.Praza@Sun.COM 	scf_instance_t *tmpl_inst = NULL;
1165*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
1166*7887SLiane.Praza@Sun.COM 	int ret;
1167*7887SLiane.Praza@Sun.COM 	char *tg = NULL;
1168*7887SLiane.Praza@Sun.COM 
1169*7887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
1170*7887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
1171*7887SLiane.Praza@Sun.COM 
1172*7887SLiane.Praza@Sun.COM 	if (inst != NULL)
1173*7887SLiane.Praza@Sun.COM 		h = scf_instance_handle(inst);
1174*7887SLiane.Praza@Sun.COM 	else
1175*7887SLiane.Praza@Sun.COM 		h = scf_service_handle(svc);
1176*7887SLiane.Praza@Sun.COM 	if (h == NULL)
1177*7887SLiane.Praza@Sun.COM 		goto done;
1178*7887SLiane.Praza@Sun.COM 
1179*7887SLiane.Praza@Sun.COM 	/* First, use supplied service or instance */
1180*7887SLiane.Praza@Sun.COM 	p->pw_target = SCF_TM_TARGET_THIS;
1181*7887SLiane.Praza@Sun.COM 	ret = func(svc, inst, p);
1182*7887SLiane.Praza@Sun.COM 	switch (ret) {
1183*7887SLiane.Praza@Sun.COM 	case SCF_WALK_NEXT:
1184*7887SLiane.Praza@Sun.COM 		break;
1185*7887SLiane.Praza@Sun.COM 	case SCF_WALK_DONE:
1186*7887SLiane.Praza@Sun.COM 		/*
1187*7887SLiane.Praza@Sun.COM 		 * Check that the template scoping matches and if not,
1188*7887SLiane.Praza@Sun.COM 		 * continue.
1189*7887SLiane.Praza@Sun.COM 		 */
1190*7887SLiane.Praza@Sun.COM 		assert(p->pw_pg != NULL);
1191*7887SLiane.Praza@Sun.COM 		tg = _scf_read_single_astring_from_pg(p->pw_pg,
1192*7887SLiane.Praza@Sun.COM 		    SCF_PROPERTY_TM_TARGET);
1193*7887SLiane.Praza@Sun.COM 		if (tg == NULL || /* scf_error() was set */
1194*7887SLiane.Praza@Sun.COM 		    (strcmp(tg, SCF_TM_TARGET_INSTANCE) != 0 &&
1195*7887SLiane.Praza@Sun.COM 		    strcmp(tg, SCF_TM_TARGET_THIS) != 0 &&
1196*7887SLiane.Praza@Sun.COM 		    (flag & SCF_PG_TMPL_FLAG_EXACT) !=
1197*7887SLiane.Praza@Sun.COM 		    SCF_PG_TMPL_FLAG_EXACT)) {
1198*7887SLiane.Praza@Sun.COM 			scf_pg_destroy(p->pw_pg);
1199*7887SLiane.Praza@Sun.COM 			p->pw_pg = NULL;
1200*7887SLiane.Praza@Sun.COM 			if (tg != NULL) {
1201*7887SLiane.Praza@Sun.COM 				free(tg);
1202*7887SLiane.Praza@Sun.COM 				tg = NULL;
1203*7887SLiane.Praza@Sun.COM 				break;
1204*7887SLiane.Praza@Sun.COM 			}
1205*7887SLiane.Praza@Sun.COM 		}
1206*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
1207*7887SLiane.Praza@Sun.COM 	case SCF_WALK_ERROR:
1208*7887SLiane.Praza@Sun.COM 		goto done;
1209*7887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
1210*7887SLiane.Praza@Sun.COM 	default:
1211*7887SLiane.Praza@Sun.COM 		assert(0);
1212*7887SLiane.Praza@Sun.COM 		abort();
1213*7887SLiane.Praza@Sun.COM 	}
1214*7887SLiane.Praza@Sun.COM 
1215*7887SLiane.Praza@Sun.COM 	/* Next the restarter. */
1216*7887SLiane.Praza@Sun.COM 	p->pw_target = SCF_TM_TARGET_DELEGATE;
1217*7887SLiane.Praza@Sun.COM 	tmpl_inst = _get_restarter_inst(h, svc, inst, snap);
1218*7887SLiane.Praza@Sun.COM 	if (tmpl_inst != NULL) {
1219*7887SLiane.Praza@Sun.COM 		ret = func(NULL, tmpl_inst, p);
1220*7887SLiane.Praza@Sun.COM 		switch (ret) {
1221*7887SLiane.Praza@Sun.COM 		case SCF_WALK_NEXT:
1222*7887SLiane.Praza@Sun.COM 			break;
1223*7887SLiane.Praza@Sun.COM 		case SCF_WALK_DONE:
1224*7887SLiane.Praza@Sun.COM 			/*
1225*7887SLiane.Praza@Sun.COM 			 * Check that the template scoping matches and if not,
1226*7887SLiane.Praza@Sun.COM 			 * continue.
1227*7887SLiane.Praza@Sun.COM 			 */
1228*7887SLiane.Praza@Sun.COM 			assert(p->pw_pg != NULL);
1229*7887SLiane.Praza@Sun.COM 			tg = _scf_read_single_astring_from_pg(p->pw_pg,
1230*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_TARGET);
1231*7887SLiane.Praza@Sun.COM 			if (tg == NULL || /* scf_error() was set */
1232*7887SLiane.Praza@Sun.COM 			    strcmp(tg, SCF_TM_TARGET_DELEGATE) != 0) {
1233*7887SLiane.Praza@Sun.COM 				scf_pg_destroy(p->pw_pg);
1234*7887SLiane.Praza@Sun.COM 				p->pw_pg = NULL;
1235*7887SLiane.Praza@Sun.COM 				if (tg != NULL) {
1236*7887SLiane.Praza@Sun.COM 					free(tg);
1237*7887SLiane.Praza@Sun.COM 					tg = NULL;
1238*7887SLiane.Praza@Sun.COM 					break;
1239*7887SLiane.Praza@Sun.COM 				}
1240*7887SLiane.Praza@Sun.COM 			}
1241*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
1242*7887SLiane.Praza@Sun.COM 		case SCF_WALK_ERROR:
1243*7887SLiane.Praza@Sun.COM 			goto done;
1244*7887SLiane.Praza@Sun.COM 			/*NOTREACHED*/
1245*7887SLiane.Praza@Sun.COM 		default:
1246*7887SLiane.Praza@Sun.COM 			assert(0);
1247*7887SLiane.Praza@Sun.COM 			abort();
1248*7887SLiane.Praza@Sun.COM 		}
1249*7887SLiane.Praza@Sun.COM 	}
1250*7887SLiane.Praza@Sun.COM 
1251*7887SLiane.Praza@Sun.COM 	p->pw_target = SCF_TM_TARGET_ALL;
1252*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(tmpl_inst);
1253*7887SLiane.Praza@Sun.COM 	tmpl_inst = _get_global_inst(h);
1254*7887SLiane.Praza@Sun.COM 	if (tmpl_inst != NULL) {
1255*7887SLiane.Praza@Sun.COM 		ret = func(NULL, tmpl_inst, p);
1256*7887SLiane.Praza@Sun.COM 		switch (ret) {
1257*7887SLiane.Praza@Sun.COM 		case SCF_WALK_NEXT:
1258*7887SLiane.Praza@Sun.COM 			break;
1259*7887SLiane.Praza@Sun.COM 		case SCF_WALK_DONE:
1260*7887SLiane.Praza@Sun.COM 			/*
1261*7887SLiane.Praza@Sun.COM 			 * Check that the template scoping matches and if not,
1262*7887SLiane.Praza@Sun.COM 			 * continue.
1263*7887SLiane.Praza@Sun.COM 			 */
1264*7887SLiane.Praza@Sun.COM 			assert(p->pw_pg != NULL);
1265*7887SLiane.Praza@Sun.COM 			tg = _scf_read_single_astring_from_pg(p->pw_pg,
1266*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_TARGET);
1267*7887SLiane.Praza@Sun.COM 			if (tg == NULL || /* scf_error() was set */
1268*7887SLiane.Praza@Sun.COM 			    strcmp(tg, SCF_TM_TARGET_ALL) != 0) {
1269*7887SLiane.Praza@Sun.COM 				scf_pg_destroy(p->pw_pg);
1270*7887SLiane.Praza@Sun.COM 				p->pw_pg = NULL;
1271*7887SLiane.Praza@Sun.COM 				if (tg != NULL) {
1272*7887SLiane.Praza@Sun.COM 					free(tg);
1273*7887SLiane.Praza@Sun.COM 					tg = NULL;
1274*7887SLiane.Praza@Sun.COM 					break;
1275*7887SLiane.Praza@Sun.COM 				}
1276*7887SLiane.Praza@Sun.COM 			}
1277*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
1278*7887SLiane.Praza@Sun.COM 		case SCF_WALK_ERROR:
1279*7887SLiane.Praza@Sun.COM 			goto done;
1280*7887SLiane.Praza@Sun.COM 			/*NOTREACHED*/
1281*7887SLiane.Praza@Sun.COM 		default:
1282*7887SLiane.Praza@Sun.COM 			assert(0);
1283*7887SLiane.Praza@Sun.COM 			abort();
1284*7887SLiane.Praza@Sun.COM 		}
1285*7887SLiane.Praza@Sun.COM 	}
1286*7887SLiane.Praza@Sun.COM 
1287*7887SLiane.Praza@Sun.COM done:
1288*7887SLiane.Praza@Sun.COM 	free(tg);
1289*7887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_DONE)
1290*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(tmpl_inst);
1291*7887SLiane.Praza@Sun.COM 	p->pw_target = NULL;
1292*7887SLiane.Praza@Sun.COM }
1293*7887SLiane.Praza@Sun.COM 
1294*7887SLiane.Praza@Sun.COM /*
1295*7887SLiane.Praza@Sun.COM  * _get_pg() returns 0 on success and -1 on failure.  Sets scf_error()
1296*7887SLiane.Praza@Sun.COM  * on failure.
1297*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
1298*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
1299*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
1300*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_MISMATCH
1301*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
1302*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
1303*7887SLiane.Praza@Sun.COM  *     name is not a valid property group.
1304*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
1305*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
1306*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
1307*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
1308*7887SLiane.Praza@Sun.COM  */
1309*7887SLiane.Praza@Sun.COM static int
1310*7887SLiane.Praza@Sun.COM _get_pg(scf_service_t *svc, scf_instance_t *inst,
1311*7887SLiane.Praza@Sun.COM     const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg)
1312*7887SLiane.Praza@Sun.COM {
1313*7887SLiane.Praza@Sun.COM 	int ret;
1314*7887SLiane.Praza@Sun.COM 
1315*7887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
1316*7887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
1317*7887SLiane.Praza@Sun.COM 	assert(pg != NULL);
1318*7887SLiane.Praza@Sun.COM 
1319*7887SLiane.Praza@Sun.COM 	if (inst != NULL)
1320*7887SLiane.Praza@Sun.COM 		ret = scf_instance_get_pg_composed(inst, snap, name, pg);
1321*7887SLiane.Praza@Sun.COM 	else
1322*7887SLiane.Praza@Sun.COM 		ret = scf_service_get_pg(svc, name, pg);
1323*7887SLiane.Praza@Sun.COM 
1324*7887SLiane.Praza@Sun.COM 	return (ret);
1325*7887SLiane.Praza@Sun.COM }
1326*7887SLiane.Praza@Sun.COM 
1327*7887SLiane.Praza@Sun.COM /*
1328*7887SLiane.Praza@Sun.COM  * Returns SCF_WALK_NEXT for not found, SCF_WALK_ERROR for error,
1329*7887SLiane.Praza@Sun.COM  * and SCF_WALK_DONE for found.
1330*7887SLiane.Praza@Sun.COM  * On error, destroy pg and set it to NULL.
1331*7887SLiane.Praza@Sun.COM  *
1332*7887SLiane.Praza@Sun.COM  * Sets scf_error() if SCF_WALK_ERROR is returned to _BACKEND_ACCESS,
1333*7887SLiane.Praza@Sun.COM  * _CONNECTION_BROKEN, _INTERNAL, _INVALID_ARGUMENT (name is not a
1334*7887SLiane.Praza@Sun.COM  *  valid property group), _NO_RESOURCES, or _NOT_BOUND.
1335*7887SLiane.Praza@Sun.COM  */
1336*7887SLiane.Praza@Sun.COM static int
1337*7887SLiane.Praza@Sun.COM _lookup_pg(scf_service_t *svc, scf_instance_t *inst,
1338*7887SLiane.Praza@Sun.COM     const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg)
1339*7887SLiane.Praza@Sun.COM {
1340*7887SLiane.Praza@Sun.COM 	int ret;
1341*7887SLiane.Praza@Sun.COM 
1342*7887SLiane.Praza@Sun.COM 	ret = _get_pg(svc, inst, snap, name, pg);
1343*7887SLiane.Praza@Sun.COM 
1344*7887SLiane.Praza@Sun.COM 	if (ret == 0) {
1345*7887SLiane.Praza@Sun.COM 		return (SCF_WALK_DONE);
1346*7887SLiane.Praza@Sun.COM 	} else {
1347*7887SLiane.Praza@Sun.COM 		switch (scf_error()) {
1348*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
1349*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_DELETED:
1350*7887SLiane.Praza@Sun.COM 			return (SCF_WALK_NEXT);
1351*7887SLiane.Praza@Sun.COM 
1352*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_BACKEND_ACCESS:
1353*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONNECTION_BROKEN:
1354*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INTERNAL:
1355*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
1356*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_BOUND:
1357*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NO_RESOURCES:
1358*7887SLiane.Praza@Sun.COM 			scf_pg_destroy(pg);
1359*7887SLiane.Praza@Sun.COM 			pg = NULL;
1360*7887SLiane.Praza@Sun.COM 			return (SCF_WALK_ERROR);
1361*7887SLiane.Praza@Sun.COM 
1362*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1363*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
1364*7887SLiane.Praza@Sun.COM 		default:
1365*7887SLiane.Praza@Sun.COM 			assert(0);
1366*7887SLiane.Praza@Sun.COM 			abort();
1367*7887SLiane.Praza@Sun.COM 		}
1368*7887SLiane.Praza@Sun.COM 	}
1369*7887SLiane.Praza@Sun.COM 
1370*7887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
1371*7887SLiane.Praza@Sun.COM }
1372*7887SLiane.Praza@Sun.COM 
1373*7887SLiane.Praza@Sun.COM /*
1374*7887SLiane.Praza@Sun.COM  * If match, return 0.  If no match, return 1.  If error, return -1.
1375*7887SLiane.Praza@Sun.COM  * On error set scf_error() to _BACKEND_ACCESS, _CONNECTION_BROKEN,
1376*7887SLiane.Praza@Sun.COM  * _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, _NO_RESOURCES, _NOT_BOUND,
1377*7887SLiane.Praza@Sun.COM  * _NOT_SET (property group specified by pg is not set), _PERMISSION_DENIED,
1378*7887SLiane.Praza@Sun.COM  * or _TEMPLATE_INVALID (target property is not SCF_TYPE_ASTRING or has
1379*7887SLiane.Praza@Sun.COM  * more than one value).
1380*7887SLiane.Praza@Sun.COM  */
1381*7887SLiane.Praza@Sun.COM static int
1382*7887SLiane.Praza@Sun.COM check_target_match(scf_propertygroup_t *pg, const char *target)
1383*7887SLiane.Praza@Sun.COM {
1384*7887SLiane.Praza@Sun.COM 	char *pg_target;
1385*7887SLiane.Praza@Sun.COM 	int ret = 0;
1386*7887SLiane.Praza@Sun.COM 
1387*7887SLiane.Praza@Sun.COM 	pg_target = _scf_read_single_astring_from_pg(pg,
1388*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TARGET);
1389*7887SLiane.Praza@Sun.COM 	if (pg_target == NULL) {
1390*7887SLiane.Praza@Sun.COM 		switch (scf_error()) {
1391*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_DELETED:
1392*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
1393*7887SLiane.Praza@Sun.COM 			return (1);
1394*7887SLiane.Praza@Sun.COM 
1395*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1396*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
1397*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(
1398*7887SLiane.Praza@Sun.COM 			    SCF_ERROR_TEMPLATE_INVALID);
1399*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
1400*7887SLiane.Praza@Sun.COM 
1401*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_BACKEND_ACCESS:
1402*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONNECTION_BROKEN:
1403*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_DESTROYED:
1404*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INTERNAL:
1405*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NO_RESOURCES:
1406*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_BOUND:
1407*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_PERMISSION_DENIED:
1408*7887SLiane.Praza@Sun.COM 			return (-1);
1409*7887SLiane.Praza@Sun.COM 
1410*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1411*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
1412*7887SLiane.Praza@Sun.COM 		default:
1413*7887SLiane.Praza@Sun.COM 			assert(0);
1414*7887SLiane.Praza@Sun.COM 			abort();
1415*7887SLiane.Praza@Sun.COM 		}
1416*7887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
1417*7887SLiane.Praza@Sun.COM 	}
1418*7887SLiane.Praza@Sun.COM 
1419*7887SLiane.Praza@Sun.COM 	/* For a desired target of 'this', check for 'this' and 'instance'. */
1420*7887SLiane.Praza@Sun.COM 	if ((strcmp(target, SCF_TM_TARGET_INSTANCE) == 0 ||
1421*7887SLiane.Praza@Sun.COM 	    strcmp(target, SCF_TM_TARGET_THIS) == 0) &&
1422*7887SLiane.Praza@Sun.COM 	    (strcmp(pg_target, SCF_TM_TARGET_INSTANCE) == 0 ||
1423*7887SLiane.Praza@Sun.COM 	    strcmp(pg_target, SCF_TM_TARGET_THIS) == 0)) {
1424*7887SLiane.Praza@Sun.COM 		goto cleanup;
1425*7887SLiane.Praza@Sun.COM 	}
1426*7887SLiane.Praza@Sun.COM 
1427*7887SLiane.Praza@Sun.COM 	if (strcmp(target, SCF_TM_TARGET_DELEGATE) == 0 &&
1428*7887SLiane.Praza@Sun.COM 	    strcmp(pg_target, SCF_TM_TARGET_DELEGATE) == 0) {
1429*7887SLiane.Praza@Sun.COM 		goto cleanup;
1430*7887SLiane.Praza@Sun.COM 	}
1431*7887SLiane.Praza@Sun.COM 
1432*7887SLiane.Praza@Sun.COM 	if (strcmp(target, SCF_TM_TARGET_ALL) == 0 &&
1433*7887SLiane.Praza@Sun.COM 	    strcmp(pg_target, SCF_TM_TARGET_ALL) == 0) {
1434*7887SLiane.Praza@Sun.COM 		goto cleanup;
1435*7887SLiane.Praza@Sun.COM 	}
1436*7887SLiane.Praza@Sun.COM 
1437*7887SLiane.Praza@Sun.COM 	ret = 1;
1438*7887SLiane.Praza@Sun.COM cleanup:
1439*7887SLiane.Praza@Sun.COM 	free(pg_target);
1440*7887SLiane.Praza@Sun.COM 	return (ret);
1441*7887SLiane.Praza@Sun.COM }
1442*7887SLiane.Praza@Sun.COM 
1443*7887SLiane.Praza@Sun.COM /*
1444*7887SLiane.Praza@Sun.COM  * Check if a matching template property group exists for each of:
1445*7887SLiane.Praza@Sun.COM  * name and type, name only, type only, and completely wildcarded
1446*7887SLiane.Praza@Sun.COM  * template.
1447*7887SLiane.Praza@Sun.COM  *
1448*7887SLiane.Praza@Sun.COM  * Both pg_name and pg_type are optional.
1449*7887SLiane.Praza@Sun.COM  *
1450*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error():
1451*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
1452*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
1453*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
1454*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
1455*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
1456*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
1457*7887SLiane.Praza@Sun.COM  *     can't combine the _tmpl_pg_name arguments and get a reasonable
1458*7887SLiane.Praza@Sun.COM  *     length name, or pg_name is not a valid property group.
1459*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
1460*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
1461*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
1462*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
1463*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
1464*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
1465*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
1466*7887SLiane.Praza@Sun.COM  *     target property is not SCF_TYPE_ASTRING or has more than one value.
1467*7887SLiane.Praza@Sun.COM  */
1468*7887SLiane.Praza@Sun.COM static scf_propertygroup_t *
1469*7887SLiane.Praza@Sun.COM _find_template_pg_match(scf_service_t *svc, scf_instance_t *inst,
1470*7887SLiane.Praza@Sun.COM     const scf_snapshot_t *snap, const char *pg_name, const char *pg_type,
1471*7887SLiane.Praza@Sun.COM     const char *target, char **tmpl_pg_name)
1472*7887SLiane.Praza@Sun.COM {
1473*7887SLiane.Praza@Sun.COM 	int ret, r;
1474*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
1475*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
1476*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter;
1477*7887SLiane.Praza@Sun.COM 	char *name, *type;
1478*7887SLiane.Praza@Sun.COM 
1479*7887SLiane.Praza@Sun.COM 	assert(inst != NULL || svc != NULL);
1480*7887SLiane.Praza@Sun.COM 	assert(inst == NULL || svc == NULL);
1481*7887SLiane.Praza@Sun.COM 
1482*7887SLiane.Praza@Sun.COM 	if (inst != NULL)
1483*7887SLiane.Praza@Sun.COM 		h = scf_instance_handle(inst);
1484*7887SLiane.Praza@Sun.COM 	else
1485*7887SLiane.Praza@Sun.COM 		h = scf_service_handle(svc);
1486*7887SLiane.Praza@Sun.COM 	if (h == NULL) {
1487*7887SLiane.Praza@Sun.COM 		return (NULL);
1488*7887SLiane.Praza@Sun.COM 	}
1489*7887SLiane.Praza@Sun.COM 
1490*7887SLiane.Praza@Sun.COM 	if ((pg = scf_pg_create(h)) == NULL ||
1491*7887SLiane.Praza@Sun.COM 	    (iter = scf_iter_create(h)) == NULL) {
1492*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
1493*7887SLiane.Praza@Sun.COM 		scf_pg_destroy(pg);
1494*7887SLiane.Praza@Sun.COM 		return (NULL);
1495*7887SLiane.Praza@Sun.COM 	}
1496*7887SLiane.Praza@Sun.COM 
1497*7887SLiane.Praza@Sun.COM 	/*
1498*7887SLiane.Praza@Sun.COM 	 * We're going to walk through the possible pg templates that
1499*7887SLiane.Praza@Sun.COM 	 * could match the supplied name and type.  We do this
1500*7887SLiane.Praza@Sun.COM 	 * by explicit name lookups when possible to avoid having to
1501*7887SLiane.Praza@Sun.COM 	 * keep track of a most-explicit-match during iteration.
1502*7887SLiane.Praza@Sun.COM 	 */
1503*7887SLiane.Praza@Sun.COM 
1504*7887SLiane.Praza@Sun.COM 	/* First look for a template with name and type set and matching. */
1505*7887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(pg_name, pg_type, 1);
1506*7887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
1507*7887SLiane.Praza@Sun.COM 		goto fail;
1508*7887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
1509*7887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
1510*7887SLiane.Praza@Sun.COM 		if (pg != NULL) {
1511*7887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
1512*7887SLiane.Praza@Sun.COM 				goto done;
1513*7887SLiane.Praza@Sun.COM 			else if (r == -1)
1514*7887SLiane.Praza@Sun.COM 				goto fail;
1515*7887SLiane.Praza@Sun.COM 		} else {
1516*7887SLiane.Praza@Sun.COM 			goto done;
1517*7887SLiane.Praza@Sun.COM 		}
1518*7887SLiane.Praza@Sun.COM 	}
1519*7887SLiane.Praza@Sun.COM 	free(*tmpl_pg_name);
1520*7887SLiane.Praza@Sun.COM 
1521*7887SLiane.Praza@Sun.COM 	/*
1522*7887SLiane.Praza@Sun.COM 	 * Need to search on a name-only match before searching on
1523*7887SLiane.Praza@Sun.COM 	 * type matches.
1524*7887SLiane.Praza@Sun.COM 	 */
1525*7887SLiane.Praza@Sun.COM 
1526*7887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(pg_name, NULL, 0);
1527*7887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
1528*7887SLiane.Praza@Sun.COM 		goto fail;
1529*7887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
1530*7887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
1531*7887SLiane.Praza@Sun.COM 		if (pg != NULL) {
1532*7887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
1533*7887SLiane.Praza@Sun.COM 				goto done;
1534*7887SLiane.Praza@Sun.COM 			else if (r == -1)
1535*7887SLiane.Praza@Sun.COM 				goto fail;
1536*7887SLiane.Praza@Sun.COM 		} else {
1537*7887SLiane.Praza@Sun.COM 			goto done;
1538*7887SLiane.Praza@Sun.COM 		}
1539*7887SLiane.Praza@Sun.COM 	}
1540*7887SLiane.Praza@Sun.COM 	free(*tmpl_pg_name);
1541*7887SLiane.Praza@Sun.COM 
1542*7887SLiane.Praza@Sun.COM 	/* Next, see if there's an "nt" template where the type matches. */
1543*7887SLiane.Praza@Sun.COM 	if (pg_type != NULL && pg_name == NULL) {
1544*7887SLiane.Praza@Sun.COM 		if (inst != NULL)
1545*7887SLiane.Praza@Sun.COM 			ret = scf_iter_instance_pgs_typed_composed(iter, inst,
1546*7887SLiane.Praza@Sun.COM 			    snap, SCF_GROUP_TEMPLATE_PG_PATTERN);
1547*7887SLiane.Praza@Sun.COM 		else
1548*7887SLiane.Praza@Sun.COM 			ret = scf_iter_service_pgs_typed(iter, svc,
1549*7887SLiane.Praza@Sun.COM 			    SCF_GROUP_TEMPLATE_PG_PATTERN);
1550*7887SLiane.Praza@Sun.COM 
1551*7887SLiane.Praza@Sun.COM 		if (ret != 0) {
1552*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
1553*7887SLiane.Praza@Sun.COM 				goto fail;
1554*7887SLiane.Praza@Sun.COM 			} else {
1555*7887SLiane.Praza@Sun.COM 				assert(0);
1556*7887SLiane.Praza@Sun.COM 				abort();
1557*7887SLiane.Praza@Sun.COM 			}
1558*7887SLiane.Praza@Sun.COM 		}
1559*7887SLiane.Praza@Sun.COM 
1560*7887SLiane.Praza@Sun.COM 		while ((ret = scf_iter_next_pg(iter, pg)) == 1) {
1561*7887SLiane.Praza@Sun.COM 			/* Make sure this is a name and type specified pg. */
1562*7887SLiane.Praza@Sun.COM 			name = _scf_read_single_astring_from_pg(pg,
1563*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_NAME);
1564*7887SLiane.Praza@Sun.COM 			if (name == NULL)
1565*7887SLiane.Praza@Sun.COM 				continue;
1566*7887SLiane.Praza@Sun.COM 			type = _scf_read_single_astring_from_pg(pg,
1567*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_TYPE);
1568*7887SLiane.Praza@Sun.COM 			if (type == NULL) {
1569*7887SLiane.Praza@Sun.COM 				free(name);
1570*7887SLiane.Praza@Sun.COM 				continue;
1571*7887SLiane.Praza@Sun.COM 			}
1572*7887SLiane.Praza@Sun.COM 			if (strcmp(pg_type, type) == 0 &&
1573*7887SLiane.Praza@Sun.COM 			    check_target_match(pg, target) == 0) {
1574*7887SLiane.Praza@Sun.COM 				*tmpl_pg_name = name;
1575*7887SLiane.Praza@Sun.COM 				free(type);
1576*7887SLiane.Praza@Sun.COM 				goto done;
1577*7887SLiane.Praza@Sun.COM 			}
1578*7887SLiane.Praza@Sun.COM 			free(type);
1579*7887SLiane.Praza@Sun.COM 			free(name);
1580*7887SLiane.Praza@Sun.COM 		}
1581*7887SLiane.Praza@Sun.COM 		if (ret == -1) {
1582*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
1583*7887SLiane.Praza@Sun.COM 				goto fail;
1584*7887SLiane.Praza@Sun.COM 			} else {
1585*7887SLiane.Praza@Sun.COM 				assert(0);
1586*7887SLiane.Praza@Sun.COM 				abort();
1587*7887SLiane.Praza@Sun.COM 			}
1588*7887SLiane.Praza@Sun.COM 		}
1589*7887SLiane.Praza@Sun.COM 	}
1590*7887SLiane.Praza@Sun.COM 
1591*7887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(NULL, pg_type, 0);
1592*7887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
1593*7887SLiane.Praza@Sun.COM 		goto fail;
1594*7887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
1595*7887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
1596*7887SLiane.Praza@Sun.COM 		if (pg != NULL) {
1597*7887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
1598*7887SLiane.Praza@Sun.COM 				goto done;
1599*7887SLiane.Praza@Sun.COM 			else if (r == -1)
1600*7887SLiane.Praza@Sun.COM 				goto fail;
1601*7887SLiane.Praza@Sun.COM 		} else {
1602*7887SLiane.Praza@Sun.COM 			goto done;
1603*7887SLiane.Praza@Sun.COM 		}
1604*7887SLiane.Praza@Sun.COM 	}
1605*7887SLiane.Praza@Sun.COM 	free(*tmpl_pg_name);
1606*7887SLiane.Praza@Sun.COM 
1607*7887SLiane.Praza@Sun.COM 	*tmpl_pg_name = _tmpl_pg_name(NULL, NULL, 0);
1608*7887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name == NULL)
1609*7887SLiane.Praza@Sun.COM 		goto fail;
1610*7887SLiane.Praza@Sun.COM 	ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg);
1611*7887SLiane.Praza@Sun.COM 	if (ret != SCF_WALK_NEXT) {
1612*7887SLiane.Praza@Sun.COM 		if (pg != NULL) {
1613*7887SLiane.Praza@Sun.COM 			if ((r = check_target_match(pg, target)) == 0)
1614*7887SLiane.Praza@Sun.COM 				goto done;
1615*7887SLiane.Praza@Sun.COM 			else if (r == -1)
1616*7887SLiane.Praza@Sun.COM 				goto fail;
1617*7887SLiane.Praza@Sun.COM 		} else {
1618*7887SLiane.Praza@Sun.COM 			goto done;
1619*7887SLiane.Praza@Sun.COM 		}
1620*7887SLiane.Praza@Sun.COM 	}
1621*7887SLiane.Praza@Sun.COM 
1622*7887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NOT_FOUND);
1623*7887SLiane.Praza@Sun.COM fail:
1624*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
1625*7887SLiane.Praza@Sun.COM 	if (*tmpl_pg_name != NULL)
1626*7887SLiane.Praza@Sun.COM 		free(*tmpl_pg_name);
1627*7887SLiane.Praza@Sun.COM 	*tmpl_pg_name = NULL;
1628*7887SLiane.Praza@Sun.COM 	pg = NULL;
1629*7887SLiane.Praza@Sun.COM done:
1630*7887SLiane.Praza@Sun.COM 	if (ret == SCF_WALK_ERROR)
1631*7887SLiane.Praza@Sun.COM 		free(*tmpl_pg_name);
1632*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
1633*7887SLiane.Praza@Sun.COM 	return (pg);
1634*7887SLiane.Praza@Sun.COM }
1635*7887SLiane.Praza@Sun.COM 
1636*7887SLiane.Praza@Sun.COM /*
1637*7887SLiane.Praza@Sun.COM  * Finds the pg match in either the supplied service or instance.
1638*7887SLiane.Praza@Sun.COM  * Returns SCF_WALK_ERROR, SCF_WALK_NEXT, or SCF_WALK_DONE.
1639*7887SLiane.Praza@Sun.COM  * If returning SCF_WALK_ERROR, sets scf_error():
1640*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
1641*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
1642*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
1643*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
1644*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
1645*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
1646*7887SLiane.Praza@Sun.COM  *     The snaphot is not a valid snapshot name,
1647*7887SLiane.Praza@Sun.COM  *     or can't create a reasonable property group template name.
1648*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
1649*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
1650*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
1651*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
1652*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
1653*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
1654*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
1655*7887SLiane.Praza@Sun.COM  *     target property is not SCF_TYPE_ASTRING or has more than one value.
1656*7887SLiane.Praza@Sun.COM  */
1657*7887SLiane.Praza@Sun.COM static int
1658*7887SLiane.Praza@Sun.COM find_pg_match(scf_service_t *svc, scf_instance_t *inst, pg_tmpl_walk_t *p)
1659*7887SLiane.Praza@Sun.COM {
1660*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *tmpl_snap = NULL;
1661*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg;
1662*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
1663*7887SLiane.Praza@Sun.COM 	char *tmpl_pg_name;
1664*7887SLiane.Praza@Sun.COM 
1665*7887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
1666*7887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
1667*7887SLiane.Praza@Sun.COM 
1668*7887SLiane.Praza@Sun.COM 	if (inst != NULL)
1669*7887SLiane.Praza@Sun.COM 		h = scf_instance_handle(inst);
1670*7887SLiane.Praza@Sun.COM 	else
1671*7887SLiane.Praza@Sun.COM 		h = scf_service_handle(svc);
1672*7887SLiane.Praza@Sun.COM 	if (h == NULL)
1673*7887SLiane.Praza@Sun.COM 		return (SCF_WALK_ERROR);
1674*7887SLiane.Praza@Sun.COM 
1675*7887SLiane.Praza@Sun.COM 	if (p->pw_snapname != NULL) {
1676*7887SLiane.Praza@Sun.COM 		if (_get_snapshot(inst, p->pw_snapname, &tmpl_snap) == -1)
1677*7887SLiane.Praza@Sun.COM 			return (SCF_WALK_ERROR);
1678*7887SLiane.Praza@Sun.COM 	}
1679*7887SLiane.Praza@Sun.COM 	pg = _find_template_pg_match(svc, inst, tmpl_snap, p->pw_pgname,
1680*7887SLiane.Praza@Sun.COM 	    p->pw_pgtype, p->pw_target, &tmpl_pg_name);
1681*7887SLiane.Praza@Sun.COM 
1682*7887SLiane.Praza@Sun.COM 	if (pg != NULL) {
1683*7887SLiane.Praza@Sun.COM 		p->pw_snap = tmpl_snap;
1684*7887SLiane.Praza@Sun.COM 		p->pw_pg = pg;
1685*7887SLiane.Praza@Sun.COM 		p->pw_tmpl_pgname = tmpl_pg_name;
1686*7887SLiane.Praza@Sun.COM 		p->pw_inst = inst;
1687*7887SLiane.Praza@Sun.COM 		p->pw_svc = svc;
1688*7887SLiane.Praza@Sun.COM 		return (SCF_WALK_DONE);
1689*7887SLiane.Praza@Sun.COM 	}
1690*7887SLiane.Praza@Sun.COM 
1691*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(tmpl_snap);
1692*7887SLiane.Praza@Sun.COM 	return (SCF_WALK_NEXT);
1693*7887SLiane.Praza@Sun.COM }
1694*7887SLiane.Praza@Sun.COM 
1695*7887SLiane.Praza@Sun.COM /*
1696*7887SLiane.Praza@Sun.COM  * return 0 on success and -1 on failure.
1697*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
1698*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
1699*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
1700*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_MISMATCH
1701*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
1702*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
1703*7887SLiane.Praza@Sun.COM  *     FMRI argument, snapshot name, pg_name, or pg is invalid.
1704*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
1705*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
1706*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
1707*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
1708*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_SET
1709*7887SLiane.Praza@Sun.COM  */
1710*7887SLiane.Praza@Sun.COM int
1711*7887SLiane.Praza@Sun.COM scf_tmpl_get_by_pg(scf_propertygroup_t *pg, scf_pg_tmpl_t *pg_tmpl, int flags)
1712*7887SLiane.Praza@Sun.COM {
1713*7887SLiane.Praza@Sun.COM 	char *fmribuf = NULL, *snapbuf = NULL, *pg_name = NULL, *pg_type = NULL;
1714*7887SLiane.Praza@Sun.COM 	int ret = 0;
1715*7887SLiane.Praza@Sun.COM 	ssize_t fbufsz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1;
1716*7887SLiane.Praza@Sun.COM 	ssize_t nbufsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
1717*7887SLiane.Praza@Sun.COM 	ssize_t tbufsz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
1718*7887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
1719*7887SLiane.Praza@Sun.COM 	scf_snaplevel_t *snaplvl = NULL;
1720*7887SLiane.Praza@Sun.COM 	scf_service_t *svc = NULL;
1721*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
1722*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
1723*7887SLiane.Praza@Sun.COM 	pg_tmpl_walk_t *p;
1724*7887SLiane.Praza@Sun.COM 
1725*7887SLiane.Praza@Sun.COM 	assert(fbufsz != 0 && nbufsz != 0 && tbufsz != 0);
1726*7887SLiane.Praza@Sun.COM 
1727*7887SLiane.Praza@Sun.COM 	scf_tmpl_pg_reset(pg_tmpl);
1728*7887SLiane.Praza@Sun.COM 
1729*7887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL)
1730*7887SLiane.Praza@Sun.COM 		return (-1);
1731*7887SLiane.Praza@Sun.COM 
1732*7887SLiane.Praza@Sun.COM 	if ((inst = scf_instance_create(h)) == NULL ||
1733*7887SLiane.Praza@Sun.COM 	    (svc = scf_service_create(h)) == NULL ||
1734*7887SLiane.Praza@Sun.COM 	    (snaplvl = scf_snaplevel_create(h)) == NULL) {
1735*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(inst);
1736*7887SLiane.Praza@Sun.COM 		scf_service_destroy(svc);
1737*7887SLiane.Praza@Sun.COM 		return (-1);
1738*7887SLiane.Praza@Sun.COM 	}
1739*7887SLiane.Praza@Sun.COM 
1740*7887SLiane.Praza@Sun.COM 	if ((fmribuf = malloc(fbufsz)) == NULL ||
1741*7887SLiane.Praza@Sun.COM 	    (pg_name = malloc(nbufsz)) == NULL ||
1742*7887SLiane.Praza@Sun.COM 	    (pg_type = malloc(tbufsz)) == NULL ||
1743*7887SLiane.Praza@Sun.COM 	    (p = calloc(1, sizeof (pg_tmpl_walk_t))) == NULL) {
1744*7887SLiane.Praza@Sun.COM 		free(fmribuf);
1745*7887SLiane.Praza@Sun.COM 		free(pg_name);
1746*7887SLiane.Praza@Sun.COM 		free(pg_type);
1747*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(inst);
1748*7887SLiane.Praza@Sun.COM 		scf_service_destroy(svc);
1749*7887SLiane.Praza@Sun.COM 		scf_snaplevel_destroy(snaplvl);
1750*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1751*7887SLiane.Praza@Sun.COM 		return (-1);
1752*7887SLiane.Praza@Sun.COM 	}
1753*7887SLiane.Praza@Sun.COM 
1754*7887SLiane.Praza@Sun.COM 	if (scf_pg_get_name(pg, pg_name, nbufsz) < 0) {
1755*7887SLiane.Praza@Sun.COM 		ret = -1;
1756*7887SLiane.Praza@Sun.COM 		goto fail;
1757*7887SLiane.Praza@Sun.COM 	}
1758*7887SLiane.Praza@Sun.COM 
1759*7887SLiane.Praza@Sun.COM 	if (scf_pg_get_type(pg, pg_type, tbufsz) < 0) {
1760*7887SLiane.Praza@Sun.COM 		ret = -1;
1761*7887SLiane.Praza@Sun.COM 		goto fail;
1762*7887SLiane.Praza@Sun.COM 	}
1763*7887SLiane.Praza@Sun.COM 	p->pw_pgname = pg_name;
1764*7887SLiane.Praza@Sun.COM 	p->pw_pgtype = pg_type;
1765*7887SLiane.Praza@Sun.COM 
1766*7887SLiane.Praza@Sun.COM 	ret = scf_pg_get_parent_snaplevel(pg, snaplvl);
1767*7887SLiane.Praza@Sun.COM 	if (ret == -1) {
1768*7887SLiane.Praza@Sun.COM 		switch (scf_error()) {
1769*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1770*7887SLiane.Praza@Sun.COM 			/* Parent type doesn't match.  Keep looking. */
1771*7887SLiane.Praza@Sun.COM 			break;
1772*7887SLiane.Praza@Sun.COM 
1773*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_DELETED:
1774*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_BOUND:
1775*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1776*7887SLiane.Praza@Sun.COM 			/* Pass these back to the caller. */
1777*7887SLiane.Praza@Sun.COM 			goto fail;
1778*7887SLiane.Praza@Sun.COM 
1779*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
1780*7887SLiane.Praza@Sun.COM 		default:
1781*7887SLiane.Praza@Sun.COM 			assert(0);
1782*7887SLiane.Praza@Sun.COM 			abort();
1783*7887SLiane.Praza@Sun.COM 		}
1784*7887SLiane.Praza@Sun.COM 
1785*7887SLiane.Praza@Sun.COM 		/*
1786*7887SLiane.Praza@Sun.COM 		 * No snapshot.  We'll use 'editing' by default since
1787*7887SLiane.Praza@Sun.COM 		 * snap and snapbuf are NULL.
1788*7887SLiane.Praza@Sun.COM 		 */
1789*7887SLiane.Praza@Sun.COM 		p->pw_snapname = NULL;
1790*7887SLiane.Praza@Sun.COM 
1791*7887SLiane.Praza@Sun.COM 	} else {
1792*7887SLiane.Praza@Sun.COM 		if ((snap = scf_snapshot_create(h)) == NULL) {
1793*7887SLiane.Praza@Sun.COM 			ret = -1;
1794*7887SLiane.Praza@Sun.COM 			goto fail;
1795*7887SLiane.Praza@Sun.COM 		}
1796*7887SLiane.Praza@Sun.COM 
1797*7887SLiane.Praza@Sun.COM 		ret = scf_snaplevel_get_parent(snaplvl, snap);
1798*7887SLiane.Praza@Sun.COM 		if (ret == -1) {
1799*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
1800*7887SLiane.Praza@Sun.COM 				ret = -1;
1801*7887SLiane.Praza@Sun.COM 				goto fail;
1802*7887SLiane.Praza@Sun.COM 			} else {
1803*7887SLiane.Praza@Sun.COM 				assert(0);
1804*7887SLiane.Praza@Sun.COM 				abort();
1805*7887SLiane.Praza@Sun.COM 			}
1806*7887SLiane.Praza@Sun.COM 		}
1807*7887SLiane.Praza@Sun.COM 
1808*7887SLiane.Praza@Sun.COM 		/* Grab snapshot name while we're here. */
1809*7887SLiane.Praza@Sun.COM 		if ((snapbuf = malloc(nbufsz)) == NULL) {
1810*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1811*7887SLiane.Praza@Sun.COM 			ret = -1;
1812*7887SLiane.Praza@Sun.COM 			goto fail;
1813*7887SLiane.Praza@Sun.COM 		}
1814*7887SLiane.Praza@Sun.COM 		if (scf_snapshot_get_name(snap, snapbuf, nbufsz) < 0) {
1815*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
1816*7887SLiane.Praza@Sun.COM 				ret = -1;
1817*7887SLiane.Praza@Sun.COM 				goto fail;
1818*7887SLiane.Praza@Sun.COM 			} else {
1819*7887SLiane.Praza@Sun.COM 				assert(0);
1820*7887SLiane.Praza@Sun.COM 				abort();
1821*7887SLiane.Praza@Sun.COM 			}
1822*7887SLiane.Praza@Sun.COM 		}
1823*7887SLiane.Praza@Sun.COM 		p->pw_snapname = snapbuf;
1824*7887SLiane.Praza@Sun.COM 
1825*7887SLiane.Praza@Sun.COM 		ret = scf_snapshot_get_parent(snap, inst);
1826*7887SLiane.Praza@Sun.COM 		if (ret == -1) {
1827*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
1828*7887SLiane.Praza@Sun.COM 				ret = -1;
1829*7887SLiane.Praza@Sun.COM 				goto fail;
1830*7887SLiane.Praza@Sun.COM 			} else {
1831*7887SLiane.Praza@Sun.COM 				assert(0);
1832*7887SLiane.Praza@Sun.COM 				abort();
1833*7887SLiane.Praza@Sun.COM 			}
1834*7887SLiane.Praza@Sun.COM 		}
1835*7887SLiane.Praza@Sun.COM 
1836*7887SLiane.Praza@Sun.COM 		_walk_template_instances(NULL, inst, snap,
1837*7887SLiane.Praza@Sun.COM 		    (walk_template_inst_func_t *)find_pg_match, p, flags);
1838*7887SLiane.Praza@Sun.COM 	}
1839*7887SLiane.Praza@Sun.COM 
1840*7887SLiane.Praza@Sun.COM 	/* No snapshot parent.  Go looking for instance parent. */
1841*7887SLiane.Praza@Sun.COM 	if (snapbuf == NULL) {
1842*7887SLiane.Praza@Sun.COM 		/* First look for instance parent. */
1843*7887SLiane.Praza@Sun.COM 		ret = scf_pg_get_parent_instance(pg, inst);
1844*7887SLiane.Praza@Sun.COM 		if (ret == 0) {
1845*7887SLiane.Praza@Sun.COM 			_walk_template_instances(NULL, inst, snap,
1846*7887SLiane.Praza@Sun.COM 			    (walk_template_inst_func_t *)find_pg_match,
1847*7887SLiane.Praza@Sun.COM 			    p, flags);
1848*7887SLiane.Praza@Sun.COM 		/* OK, check for service parent */
1849*7887SLiane.Praza@Sun.COM 		} else if (ret == -1 &&
1850*7887SLiane.Praza@Sun.COM 		    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
1851*7887SLiane.Praza@Sun.COM 			ret = scf_pg_get_parent_service(pg, svc);
1852*7887SLiane.Praza@Sun.COM 			if (ret == 0) {
1853*7887SLiane.Praza@Sun.COM 				_walk_template_instances(svc, NULL, snap,
1854*7887SLiane.Praza@Sun.COM 				    (walk_template_inst_func_t *)find_pg_match,
1855*7887SLiane.Praza@Sun.COM 				    p, flags);
1856*7887SLiane.Praza@Sun.COM 			} else {
1857*7887SLiane.Praza@Sun.COM 				switch (scf_error()) {
1858*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_CONSTRAINT_VIOLATED:
1859*7887SLiane.Praza@Sun.COM 					(void) scf_set_error(
1860*7887SLiane.Praza@Sun.COM 					    SCF_ERROR_NOT_FOUND);
1861*7887SLiane.Praza@Sun.COM 					/*FALLTHROUGH*/
1862*7887SLiane.Praza@Sun.COM 
1863*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_CONNECTION_BROKEN:
1864*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_DELETED:
1865*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_HANDLE_MISMATCH:
1866*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_NOT_BOUND:
1867*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_NOT_SET:
1868*7887SLiane.Praza@Sun.COM 					ret = -1;
1869*7887SLiane.Praza@Sun.COM 					goto fail;
1870*7887SLiane.Praza@Sun.COM 
1871*7887SLiane.Praza@Sun.COM 				default:
1872*7887SLiane.Praza@Sun.COM 					assert(0);
1873*7887SLiane.Praza@Sun.COM 					abort();
1874*7887SLiane.Praza@Sun.COM 				}
1875*7887SLiane.Praza@Sun.COM 			}
1876*7887SLiane.Praza@Sun.COM 		} else {
1877*7887SLiane.Praza@Sun.COM 			ret = -1;
1878*7887SLiane.Praza@Sun.COM 			goto fail;
1879*7887SLiane.Praza@Sun.COM 		}
1880*7887SLiane.Praza@Sun.COM 	}
1881*7887SLiane.Praza@Sun.COM 
1882*7887SLiane.Praza@Sun.COM 	if (p->pw_pg != NULL) {
1883*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_h = h;
1884*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_pg = p->pw_pg;
1885*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_inst = p->pw_inst;
1886*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_snap = p->pw_snap;
1887*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_svc = p->pw_svc;
1888*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_populated = 1;
1889*7887SLiane.Praza@Sun.COM 		free(p->pw_tmpl_pgname);
1890*7887SLiane.Praza@Sun.COM 		ret = 0;
1891*7887SLiane.Praza@Sun.COM 		goto done;
1892*7887SLiane.Praza@Sun.COM 	}
1893*7887SLiane.Praza@Sun.COM 
1894*7887SLiane.Praza@Sun.COM 	ret = -1;
1895*7887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NOT_FOUND);
1896*7887SLiane.Praza@Sun.COM 
1897*7887SLiane.Praza@Sun.COM fail:
1898*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
1899*7887SLiane.Praza@Sun.COM 	scf_service_destroy(svc);
1900*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
1901*7887SLiane.Praza@Sun.COM done:
1902*7887SLiane.Praza@Sun.COM 	free(snapbuf);
1903*7887SLiane.Praza@Sun.COM 	free(fmribuf);
1904*7887SLiane.Praza@Sun.COM 	free(pg_name);
1905*7887SLiane.Praza@Sun.COM 	free(pg_type);
1906*7887SLiane.Praza@Sun.COM 	free(p);
1907*7887SLiane.Praza@Sun.COM 	scf_snaplevel_destroy(snaplvl);
1908*7887SLiane.Praza@Sun.COM 	return (ret);
1909*7887SLiane.Praza@Sun.COM }
1910*7887SLiane.Praza@Sun.COM 
1911*7887SLiane.Praza@Sun.COM /*
1912*7887SLiane.Praza@Sun.COM  * int scf_tmpl_get_by_pg_name()
1913*7887SLiane.Praza@Sun.COM  *
1914*7887SLiane.Praza@Sun.COM  * Get a template by a combination of the name and type.  Either name
1915*7887SLiane.Praza@Sun.COM  * or type can be null, which indicates a wildcard.  flags may be
1916*7887SLiane.Praza@Sun.COM  * SCF_PG_TMPL_FLAG_CURRENT (use current properties rather than
1917*7887SLiane.Praza@Sun.COM  * the defined or running snapshot), and SCF_PG_TMPL_FLAG_EXACT (match
1918*7887SLiane.Praza@Sun.COM  * only templates defined by the FMRI in question, not by its restarter
1919*7887SLiane.Praza@Sun.COM  * or globally).  Returns 0 on success and -1 on error, and sets
1920*7887SLiane.Praza@Sun.COM  * scf_error() to:
1921*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
1922*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
1923*7887SLiane.Praza@Sun.COM  *     The connection to the repository was lost.
1924*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
1925*7887SLiane.Praza@Sun.COM  *     The instance has been deleted.
1926*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
1927*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
1928*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
1929*7887SLiane.Praza@Sun.COM  *     FMRI isn't valid, pg_name is too long to look for a template, or
1930*7887SLiane.Praza@Sun.COM  *     snapshot specified isn't a valid name
1931*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
1932*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
1933*7887SLiane.Praza@Sun.COM  *     The server does not have adequate resources to complete the request.
1934*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
1935*7887SLiane.Praza@Sun.COM  *     The handle is not currently bound.
1936*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
1937*7887SLiane.Praza@Sun.COM  *     Object matching FMRI doesn't exist in the repository, or snapshot
1938*7887SLiane.Praza@Sun.COM  *     doesn't exist.
1939*7887SLiane.Praza@Sun.COM  */
1940*7887SLiane.Praza@Sun.COM int
1941*7887SLiane.Praza@Sun.COM scf_tmpl_get_by_pg_name(const char *fmri, const char *snapshot,
1942*7887SLiane.Praza@Sun.COM     const char *pg_name, const char *pg_type, scf_pg_tmpl_t *pg_tmpl, int flags)
1943*7887SLiane.Praza@Sun.COM {
1944*7887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
1945*7887SLiane.Praza@Sun.COM 	scf_service_t *svc = NULL;
1946*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
1947*7887SLiane.Praza@Sun.COM 	pg_tmpl_walk_t *p;
1948*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
1949*7887SLiane.Praza@Sun.COM 	int ret;
1950*7887SLiane.Praza@Sun.COM 
1951*7887SLiane.Praza@Sun.COM 	assert(pg_tmpl != NULL);
1952*7887SLiane.Praza@Sun.COM 	h = pg_tmpl->pt_h;
1953*7887SLiane.Praza@Sun.COM 	assert(h != NULL);
1954*7887SLiane.Praza@Sun.COM 
1955*7887SLiane.Praza@Sun.COM 	scf_tmpl_pg_reset(pg_tmpl);
1956*7887SLiane.Praza@Sun.COM 
1957*7887SLiane.Praza@Sun.COM 	if ((inst = scf_instance_create(h)) == NULL ||
1958*7887SLiane.Praza@Sun.COM 	    (svc = scf_service_create(h)) == NULL) {
1959*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(inst);
1960*7887SLiane.Praza@Sun.COM 		return (-1);
1961*7887SLiane.Praza@Sun.COM 	}
1962*7887SLiane.Praza@Sun.COM 
1963*7887SLiane.Praza@Sun.COM 	p = calloc(1, sizeof (pg_tmpl_walk_t));
1964*7887SLiane.Praza@Sun.COM 	if (p == NULL) {
1965*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1966*7887SLiane.Praza@Sun.COM 		goto fail_zalloc;
1967*7887SLiane.Praza@Sun.COM 	}
1968*7887SLiane.Praza@Sun.COM 
1969*7887SLiane.Praza@Sun.COM 	ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL,
1970*7887SLiane.Praza@Sun.COM 	    NULL, SCF_DECODE_FMRI_EXACT);
1971*7887SLiane.Praza@Sun.COM 	if (ret == 0) {
1972*7887SLiane.Praza@Sun.COM 		scf_service_destroy(svc);
1973*7887SLiane.Praza@Sun.COM 		svc = NULL;
1974*7887SLiane.Praza@Sun.COM 	} else if (ret != 0 &&
1975*7887SLiane.Praza@Sun.COM 	    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
1976*7887SLiane.Praza@Sun.COM 		ret = scf_handle_decode_fmri(h, fmri, NULL, svc,
1977*7887SLiane.Praza@Sun.COM 		    NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT);
1978*7887SLiane.Praza@Sun.COM 		if (ret == 0) {
1979*7887SLiane.Praza@Sun.COM 			scf_instance_destroy(inst);
1980*7887SLiane.Praza@Sun.COM 			inst = NULL;
1981*7887SLiane.Praza@Sun.COM 		}
1982*7887SLiane.Praza@Sun.COM 	}
1983*7887SLiane.Praza@Sun.COM 	if (ret != 0) {
1984*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
1985*7887SLiane.Praza@Sun.COM 			goto fail;
1986*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
1987*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1988*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1989*7887SLiane.Praza@Sun.COM 			goto fail;
1990*7887SLiane.Praza@Sun.COM 
1991*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
1992*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
1993*7887SLiane.Praza@Sun.COM 			goto fail;
1994*7887SLiane.Praza@Sun.COM 
1995*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
1996*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
1997*7887SLiane.Praza@Sun.COM 		default:
1998*7887SLiane.Praza@Sun.COM 			assert(0);
1999*7887SLiane.Praza@Sun.COM 			abort();
2000*7887SLiane.Praza@Sun.COM 		}
2001*7887SLiane.Praza@Sun.COM 	}
2002*7887SLiane.Praza@Sun.COM 
2003*7887SLiane.Praza@Sun.COM 	assert(svc == NULL || inst == NULL);
2004*7887SLiane.Praza@Sun.COM 	assert(svc != NULL || inst != NULL);
2005*7887SLiane.Praza@Sun.COM 
2006*7887SLiane.Praza@Sun.COM 	if (inst != NULL) {
2007*7887SLiane.Praza@Sun.COM 		if (snapshot == NULL || strcmp(snapshot, "running") == 0 ||
2008*7887SLiane.Praza@Sun.COM 		    (flags & SCF_PG_TMPL_FLAG_CURRENT) ==
2009*7887SLiane.Praza@Sun.COM 		    SCF_PG_TMPL_FLAG_CURRENT) {
2010*7887SLiane.Praza@Sun.COM 			if (_get_snapshot(inst, NULL, &snap) == -1)
2011*7887SLiane.Praza@Sun.COM 				goto fail;
2012*7887SLiane.Praza@Sun.COM 		} else {
2013*7887SLiane.Praza@Sun.COM 			if (_get_snapshot(inst, snapshot, &snap) == -1) {
2014*7887SLiane.Praza@Sun.COM 				goto fail;
2015*7887SLiane.Praza@Sun.COM 			} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
2016*7887SLiane.Praza@Sun.COM 				goto fail;
2017*7887SLiane.Praza@Sun.COM 			}
2018*7887SLiane.Praza@Sun.COM 		}
2019*7887SLiane.Praza@Sun.COM 	} else {
2020*7887SLiane.Praza@Sun.COM 		/* If we have a service fmri, snapshot is ignored. */
2021*7887SLiane.Praza@Sun.COM 		scf_snapshot_destroy(snap);
2022*7887SLiane.Praza@Sun.COM 		snap = NULL;
2023*7887SLiane.Praza@Sun.COM 	}
2024*7887SLiane.Praza@Sun.COM 
2025*7887SLiane.Praza@Sun.COM 	p->pw_snapname = snapshot;
2026*7887SLiane.Praza@Sun.COM 	p->pw_pgname = pg_name;
2027*7887SLiane.Praza@Sun.COM 	p->pw_pgtype = pg_type;
2028*7887SLiane.Praza@Sun.COM 
2029*7887SLiane.Praza@Sun.COM 	/*
2030*7887SLiane.Praza@Sun.COM 	 * For each of instance, restarter, global
2031*7887SLiane.Praza@Sun.COM 	 *    - check for a tm_pg_pattern_nt_<name> matching type
2032*7887SLiane.Praza@Sun.COM 	 *    - check for a tm_pg_pattern_t_<type> matching type
2033*7887SLiane.Praza@Sun.COM 	 *    - check for any tm_pg_pattern_
2034*7887SLiane.Praza@Sun.COM 	 * Currently plan to return the most specific match only.
2035*7887SLiane.Praza@Sun.COM 	 */
2036*7887SLiane.Praza@Sun.COM 	_walk_template_instances(svc, inst, snap,
2037*7887SLiane.Praza@Sun.COM 	    (walk_template_inst_func_t *)find_pg_match, p, flags);
2038*7887SLiane.Praza@Sun.COM 
2039*7887SLiane.Praza@Sun.COM 	if (p->pw_pg != NULL) {
2040*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_h = h;
2041*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_pg = p->pw_pg;
2042*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_inst = p->pw_inst;
2043*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_snap = p->pw_snap;
2044*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_svc = p->pw_svc;
2045*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_populated = 1;
2046*7887SLiane.Praza@Sun.COM 		free(p->pw_tmpl_pgname);
2047*7887SLiane.Praza@Sun.COM 		free(p);
2048*7887SLiane.Praza@Sun.COM 		return (0);
2049*7887SLiane.Praza@Sun.COM 	}
2050*7887SLiane.Praza@Sun.COM 
2051*7887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_NOT_FOUND);
2052*7887SLiane.Praza@Sun.COM fail:
2053*7887SLiane.Praza@Sun.COM 	free(p);
2054*7887SLiane.Praza@Sun.COM fail_zalloc:
2055*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
2056*7887SLiane.Praza@Sun.COM 	scf_service_destroy(svc);
2057*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
2058*7887SLiane.Praza@Sun.COM 	return (-1);
2059*7887SLiane.Praza@Sun.COM }
2060*7887SLiane.Praza@Sun.COM 
2061*7887SLiane.Praza@Sun.COM /*
2062*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _CONNECTION_BROKEN,
2063*7887SLiane.Praza@Sun.COM  * _DELETED, _NO_RESOURCES, or _NOT_BOUND.
2064*7887SLiane.Praza@Sun.COM  */
2065*7887SLiane.Praza@Sun.COM static scf_iter_t *
2066*7887SLiane.Praza@Sun.COM _get_svc_or_inst_iter(scf_handle_t *h, scf_pg_tmpl_t *t)
2067*7887SLiane.Praza@Sun.COM {
2068*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter;
2069*7887SLiane.Praza@Sun.COM 	int ret;
2070*7887SLiane.Praza@Sun.COM 
2071*7887SLiane.Praza@Sun.COM 	assert(t->pt_svc != NULL || t->pt_inst != NULL);
2072*7887SLiane.Praza@Sun.COM 	assert(t->pt_svc == NULL || t->pt_inst == NULL);
2073*7887SLiane.Praza@Sun.COM 
2074*7887SLiane.Praza@Sun.COM 	if ((iter = scf_iter_create(h)) == NULL) {
2075*7887SLiane.Praza@Sun.COM 		return (NULL);
2076*7887SLiane.Praza@Sun.COM 	}
2077*7887SLiane.Praza@Sun.COM 
2078*7887SLiane.Praza@Sun.COM 	/* Iterate on property groups of type template_pg_pattern */
2079*7887SLiane.Praza@Sun.COM 
2080*7887SLiane.Praza@Sun.COM 	if (t->pt_inst != NULL)
2081*7887SLiane.Praza@Sun.COM 		ret = scf_iter_instance_pgs_typed_composed(iter,
2082*7887SLiane.Praza@Sun.COM 		    t->pt_inst, t->pt_snap,
2083*7887SLiane.Praza@Sun.COM 		    SCF_GROUP_TEMPLATE_PG_PATTERN);
2084*7887SLiane.Praza@Sun.COM 	if (t->pt_svc != NULL)
2085*7887SLiane.Praza@Sun.COM 		ret = scf_iter_service_pgs_typed(iter, t->pt_svc,
2086*7887SLiane.Praza@Sun.COM 		    SCF_GROUP_TEMPLATE_PG_PATTERN);
2087*7887SLiane.Praza@Sun.COM 
2088*7887SLiane.Praza@Sun.COM 	if (ret != 0) {
2089*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
2090*7887SLiane.Praza@Sun.COM 			scf_iter_destroy(iter);
2091*7887SLiane.Praza@Sun.COM 			return (NULL);
2092*7887SLiane.Praza@Sun.COM 		} else {
2093*7887SLiane.Praza@Sun.COM 			assert(0);
2094*7887SLiane.Praza@Sun.COM 			abort();
2095*7887SLiane.Praza@Sun.COM 		}
2096*7887SLiane.Praza@Sun.COM 	}
2097*7887SLiane.Praza@Sun.COM 
2098*7887SLiane.Praza@Sun.COM 	return (iter);
2099*7887SLiane.Praza@Sun.COM }
2100*7887SLiane.Praza@Sun.COM 
2101*7887SLiane.Praza@Sun.COM /*
2102*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
2103*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2104*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2105*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2106*7887SLiane.Praza@Sun.COM  *   SCF_HANDLE_DESTROYED
2107*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2108*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2109*7887SLiane.Praza@Sun.COM  *     Handle argument is NULL, or snaphot is not a valid snapshot name.
2110*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2111*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2112*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2113*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
2114*7887SLiane.Praza@Sun.COM  */
2115*7887SLiane.Praza@Sun.COM static scf_iter_t *
2116*7887SLiane.Praza@Sun.COM _get_next_iterator(scf_handle_t *h, scf_pg_tmpl_t *t, const char *snapshot,
2117*7887SLiane.Praza@Sun.COM     int exact)
2118*7887SLiane.Praza@Sun.COM {
2119*7887SLiane.Praza@Sun.COM 	scf_iter_t  *iter = NULL;
2120*7887SLiane.Praza@Sun.COM 	ssize_t limit;
2121*7887SLiane.Praza@Sun.COM 
2122*7887SLiane.Praza@Sun.COM 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
2123*7887SLiane.Praza@Sun.COM 	assert(limit != 0);
2124*7887SLiane.Praza@Sun.COM 
2125*7887SLiane.Praza@Sun.COM 	/*
2126*7887SLiane.Praza@Sun.COM 	 * Check what level we last iterated on: none, service,
2127*7887SLiane.Praza@Sun.COM 	 * restarter, or global.  Make sure that if one in the middle
2128*7887SLiane.Praza@Sun.COM 	 * doesn't exist, we move on to the next entity.
2129*7887SLiane.Praza@Sun.COM 	 */
2130*7887SLiane.Praza@Sun.COM 	do {
2131*7887SLiane.Praza@Sun.COM 		switch (t->pt_iter_last) {
2132*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_NONE:
2133*7887SLiane.Praza@Sun.COM 			t->pt_iter_last = SCF__TMPL_ITER_INST;
2134*7887SLiane.Praza@Sun.COM 			t->pt_inst = t->pt_orig_inst;
2135*7887SLiane.Praza@Sun.COM 			t->pt_svc = t->pt_orig_svc;
2136*7887SLiane.Praza@Sun.COM 			break;
2137*7887SLiane.Praza@Sun.COM 
2138*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_INST:
2139*7887SLiane.Praza@Sun.COM 			/*
2140*7887SLiane.Praza@Sun.COM 			 * Don't go any further than the specified instance
2141*7887SLiane.Praza@Sun.COM 			 * if exact was set.
2142*7887SLiane.Praza@Sun.COM 			 */
2143*7887SLiane.Praza@Sun.COM 			if (exact == 1) {
2144*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(SCF_ERROR_NOT_FOUND);
2145*7887SLiane.Praza@Sun.COM 				goto fail;
2146*7887SLiane.Praza@Sun.COM 			}
2147*7887SLiane.Praza@Sun.COM 			t->pt_iter_last = SCF__TMPL_ITER_RESTARTER;
2148*7887SLiane.Praza@Sun.COM 			t->pt_inst = _get_restarter_inst(h, t->pt_orig_svc,
2149*7887SLiane.Praza@Sun.COM 			    t->pt_orig_inst, t->pt_snap);
2150*7887SLiane.Praza@Sun.COM 			t->pt_svc = NULL;
2151*7887SLiane.Praza@Sun.COM 			break;
2152*7887SLiane.Praza@Sun.COM 
2153*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_RESTARTER:
2154*7887SLiane.Praza@Sun.COM 			t->pt_iter_last = SCF__TMPL_ITER_GLOBAL;
2155*7887SLiane.Praza@Sun.COM 			t->pt_inst = _get_global_inst(h);
2156*7887SLiane.Praza@Sun.COM 			t->pt_svc = NULL;
2157*7887SLiane.Praza@Sun.COM 			break;
2158*7887SLiane.Praza@Sun.COM 
2159*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_GLOBAL:
2160*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NOT_FOUND);
2161*7887SLiane.Praza@Sun.COM 			return (NULL);
2162*7887SLiane.Praza@Sun.COM 
2163*7887SLiane.Praza@Sun.COM 		default:
2164*7887SLiane.Praza@Sun.COM 			assert(0);
2165*7887SLiane.Praza@Sun.COM 			abort();
2166*7887SLiane.Praza@Sun.COM 		}
2167*7887SLiane.Praza@Sun.COM 	} while (t->pt_inst == NULL && t->pt_svc == NULL);
2168*7887SLiane.Praza@Sun.COM 
2169*7887SLiane.Praza@Sun.COM 	/* Set pt_snap to the snapshot for this instance */
2170*7887SLiane.Praza@Sun.COM 	if (t->pt_inst != NULL) {
2171*7887SLiane.Praza@Sun.COM 		scf_snapshot_destroy(t->pt_snap);
2172*7887SLiane.Praza@Sun.COM 		if (_get_snapshot(t->pt_inst, snapshot,
2173*7887SLiane.Praza@Sun.COM 		    &t->pt_snap) == -1)
2174*7887SLiane.Praza@Sun.COM 			goto fail;
2175*7887SLiane.Praza@Sun.COM 	}
2176*7887SLiane.Praza@Sun.COM 
2177*7887SLiane.Praza@Sun.COM 
2178*7887SLiane.Praza@Sun.COM 	iter = _get_svc_or_inst_iter(h, t);
2179*7887SLiane.Praza@Sun.COM fail:
2180*7887SLiane.Praza@Sun.COM 	return (iter);
2181*7887SLiane.Praza@Sun.COM }
2182*7887SLiane.Praza@Sun.COM 
2183*7887SLiane.Praza@Sun.COM /*
2184*7887SLiane.Praza@Sun.COM  * scf_pg_tmpl_t *scf_tmpl_pg_create(scf_handle_t *)
2185*7887SLiane.Praza@Sun.COM  *
2186*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT
2187*7887SLiane.Praza@Sun.COM  * or _NO_MEMORY.
2188*7887SLiane.Praza@Sun.COM  */
2189*7887SLiane.Praza@Sun.COM scf_pg_tmpl_t *
2190*7887SLiane.Praza@Sun.COM scf_tmpl_pg_create(scf_handle_t *handle)
2191*7887SLiane.Praza@Sun.COM {
2192*7887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *pg_tmpl = NULL;
2193*7887SLiane.Praza@Sun.COM 
2194*7887SLiane.Praza@Sun.COM 	if (handle == NULL) {
2195*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
2196*7887SLiane.Praza@Sun.COM 		return (NULL);
2197*7887SLiane.Praza@Sun.COM 	}
2198*7887SLiane.Praza@Sun.COM 	pg_tmpl = calloc(1, sizeof (scf_pg_tmpl_t));
2199*7887SLiane.Praza@Sun.COM 	if (pg_tmpl == NULL)
2200*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2201*7887SLiane.Praza@Sun.COM 	else
2202*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_h = handle;
2203*7887SLiane.Praza@Sun.COM 
2204*7887SLiane.Praza@Sun.COM 	return (pg_tmpl);
2205*7887SLiane.Praza@Sun.COM }
2206*7887SLiane.Praza@Sun.COM 
2207*7887SLiane.Praza@Sun.COM /*
2208*7887SLiane.Praza@Sun.COM  * Retrieves name or type of a template pg.
2209*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
2210*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2211*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2212*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2213*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2214*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2215*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2216*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2217*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2218*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
2219*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
2220*7887SLiane.Praza@Sun.COM  *     pname property is not SCF_TYPE_ASTRING or has more than one value.
2221*7887SLiane.Praza@Sun.COM  */
2222*7887SLiane.Praza@Sun.COM static ssize_t
2223*7887SLiane.Praza@Sun.COM _scf_tmpl_prop_value(scf_propertygroup_t *pg, const char *pname, char **out)
2224*7887SLiane.Praza@Sun.COM {
2225*7887SLiane.Praza@Sun.COM 	assert(strcmp(pname, SCF_PROPERTY_TM_NAME) == 0 ||
2226*7887SLiane.Praza@Sun.COM 	    strcmp(pname, SCF_PROPERTY_TM_TYPE) == 0);
2227*7887SLiane.Praza@Sun.COM 
2228*7887SLiane.Praza@Sun.COM 	*out = _scf_read_single_astring_from_pg(pg, pname);
2229*7887SLiane.Praza@Sun.COM 
2230*7887SLiane.Praza@Sun.COM 	if (*out != NULL && *out[0] == '\0') {
2231*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NONE);
2232*7887SLiane.Praza@Sun.COM 		free(*out);
2233*7887SLiane.Praza@Sun.COM 		*out = strdup(SCF_TMPL_WILDCARD);
2234*7887SLiane.Praza@Sun.COM 		if (*out == NULL)
2235*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2236*7887SLiane.Praza@Sun.COM 	}
2237*7887SLiane.Praza@Sun.COM 	if (*out == NULL) {
2238*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
2239*7887SLiane.Praza@Sun.COM 			return (-1);
2240*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
2241*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
2242*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
2243*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
2244*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
2245*7887SLiane.Praza@Sun.COM 			return (-1);
2246*7887SLiane.Praza@Sun.COM 
2247*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
2248*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
2249*7887SLiane.Praza@Sun.COM 		default:
2250*7887SLiane.Praza@Sun.COM 			assert(0);
2251*7887SLiane.Praza@Sun.COM 			abort();
2252*7887SLiane.Praza@Sun.COM 		}
2253*7887SLiane.Praza@Sun.COM 	}
2254*7887SLiane.Praza@Sun.COM 
2255*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
2256*7887SLiane.Praza@Sun.COM }
2257*7887SLiane.Praza@Sun.COM 
2258*7887SLiane.Praza@Sun.COM /*
2259*7887SLiane.Praza@Sun.COM  * int scf_tmpl_iter_pgs()
2260*7887SLiane.Praza@Sun.COM  *
2261*7887SLiane.Praza@Sun.COM  * Iterates through the property group templates for the fmri given.
2262*7887SLiane.Praza@Sun.COM  * When t is uninitialized or reset, sets t to the first property group
2263*7887SLiane.Praza@Sun.COM  * template in fmri. On subsequent calls, sets t to the next property group
2264*7887SLiane.Praza@Sun.COM  * template in frmi.
2265*7887SLiane.Praza@Sun.COM  * Returns 1 on success, 0 when no property group templates are left to
2266*7887SLiane.Praza@Sun.COM  * iterate, -1 on error.
2267*7887SLiane.Praza@Sun.COM  * The flags argument may include SCF_PG_TMPL_FLAG_REQUIRED,
2268*7887SLiane.Praza@Sun.COM  * SCF_PG_TMPL_FLAG_CURRENT,  and/or SCF_PG_TMPL_FLAG_EXACT.
2269*7887SLiane.Praza@Sun.COM  *
2270*7887SLiane.Praza@Sun.COM  * Returns -1 on error and sets scf_error() to:
2271*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2272*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2273*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2274*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2275*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2276*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2277*7887SLiane.Praza@Sun.COM  *      The handle argument is NULL, fmri is invalid, or snapshot is invalid.
2278*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2279*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2280*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2281*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
2282*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
2283*7887SLiane.Praza@Sun.COM  */
2284*7887SLiane.Praza@Sun.COM int
2285*7887SLiane.Praza@Sun.COM scf_tmpl_iter_pgs(scf_pg_tmpl_t *t, const char *fmri, const char *snapshot,
2286*7887SLiane.Praza@Sun.COM     const char *type, int flags)
2287*7887SLiane.Praza@Sun.COM {
2288*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
2289*7887SLiane.Praza@Sun.COM 	scf_service_t *svc = NULL;
2290*7887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
2291*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
2292*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
2293*7887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *pg_tmpl = NULL;
2294*7887SLiane.Praza@Sun.COM 	int err;
2295*7887SLiane.Praza@Sun.COM 	int found = 0;
2296*7887SLiane.Praza@Sun.COM 	char *tmpl_type;
2297*7887SLiane.Praza@Sun.COM 	uint8_t required;
2298*7887SLiane.Praza@Sun.COM 	int ret;
2299*7887SLiane.Praza@Sun.COM 
2300*7887SLiane.Praza@Sun.COM 	if (t == NULL) {
2301*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
2302*7887SLiane.Praza@Sun.COM 		return (-1);
2303*7887SLiane.Praza@Sun.COM 	}
2304*7887SLiane.Praza@Sun.COM 
2305*7887SLiane.Praza@Sun.COM 	h = t->pt_h;
2306*7887SLiane.Praza@Sun.COM 
2307*7887SLiane.Praza@Sun.COM 	if (t->pt_populated == 0) {
2308*7887SLiane.Praza@Sun.COM 		if ((svc = scf_service_create(h)) == NULL ||
2309*7887SLiane.Praza@Sun.COM 		    (inst = scf_instance_create(h)) == NULL ||
2310*7887SLiane.Praza@Sun.COM 		    (pg = scf_pg_create(h)) == NULL) {
2311*7887SLiane.Praza@Sun.COM 			goto fail_non_populated;
2312*7887SLiane.Praza@Sun.COM 		}
2313*7887SLiane.Praza@Sun.COM 
2314*7887SLiane.Praza@Sun.COM 		ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL,
2315*7887SLiane.Praza@Sun.COM 		    NULL, SCF_DECODE_FMRI_EXACT);
2316*7887SLiane.Praza@Sun.COM 		if (ret == 0) {
2317*7887SLiane.Praza@Sun.COM 			scf_service_destroy(svc);
2318*7887SLiane.Praza@Sun.COM 			svc = NULL;
2319*7887SLiane.Praza@Sun.COM 		} else if (ret != 0 &&
2320*7887SLiane.Praza@Sun.COM 		    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
2321*7887SLiane.Praza@Sun.COM 			ret = scf_handle_decode_fmri(h, fmri, NULL, svc,
2322*7887SLiane.Praza@Sun.COM 			    NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT);
2323*7887SLiane.Praza@Sun.COM 			if (ret == 0) {
2324*7887SLiane.Praza@Sun.COM 				scf_instance_destroy(inst);
2325*7887SLiane.Praza@Sun.COM 				inst = NULL;
2326*7887SLiane.Praza@Sun.COM 			}
2327*7887SLiane.Praza@Sun.COM 		}
2328*7887SLiane.Praza@Sun.COM 
2329*7887SLiane.Praza@Sun.COM 		if (ret != 0) {
2330*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
2331*7887SLiane.Praza@Sun.COM 				goto fail_non_populated;
2332*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
2333*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
2334*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
2335*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_INVALID_ARGUMENT);
2336*7887SLiane.Praza@Sun.COM 				goto fail_non_populated;
2337*7887SLiane.Praza@Sun.COM 
2338*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
2339*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
2340*7887SLiane.Praza@Sun.COM 				goto fail_non_populated;
2341*7887SLiane.Praza@Sun.COM 
2342*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
2343*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
2344*7887SLiane.Praza@Sun.COM 			default:
2345*7887SLiane.Praza@Sun.COM 				assert(0);
2346*7887SLiane.Praza@Sun.COM 				abort();
2347*7887SLiane.Praza@Sun.COM 			}
2348*7887SLiane.Praza@Sun.COM 		}
2349*7887SLiane.Praza@Sun.COM 
2350*7887SLiane.Praza@Sun.COM 		assert(svc == NULL || inst == NULL);
2351*7887SLiane.Praza@Sun.COM 		assert(svc != NULL || inst != NULL);
2352*7887SLiane.Praza@Sun.COM 
2353*7887SLiane.Praza@Sun.COM 		if (inst != NULL) {
2354*7887SLiane.Praza@Sun.COM 			if (snapshot == NULL ||
2355*7887SLiane.Praza@Sun.COM 			    strcmp(snapshot, "running") == 0 ||
2356*7887SLiane.Praza@Sun.COM 			    (flags & SCF_PG_TMPL_FLAG_CURRENT) ==
2357*7887SLiane.Praza@Sun.COM 			    SCF_PG_TMPL_FLAG_CURRENT) {
2358*7887SLiane.Praza@Sun.COM 				if (_get_snapshot(inst, NULL, &snap) == -1)
2359*7887SLiane.Praza@Sun.COM 					goto fail_non_populated;
2360*7887SLiane.Praza@Sun.COM 			} else {
2361*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(SCF_ERROR_NONE);
2362*7887SLiane.Praza@Sun.COM 				if (_get_snapshot(inst, snapshot,
2363*7887SLiane.Praza@Sun.COM 				    &snap) == -1) {
2364*7887SLiane.Praza@Sun.COM 					goto fail_non_populated;
2365*7887SLiane.Praza@Sun.COM 				} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
2366*7887SLiane.Praza@Sun.COM 					goto fail_non_populated;
2367*7887SLiane.Praza@Sun.COM 				}
2368*7887SLiane.Praza@Sun.COM 			}
2369*7887SLiane.Praza@Sun.COM 		} else {
2370*7887SLiane.Praza@Sun.COM 			scf_snapshot_destroy(snap);
2371*7887SLiane.Praza@Sun.COM 			snap = NULL;
2372*7887SLiane.Praza@Sun.COM 		}
2373*7887SLiane.Praza@Sun.COM 
2374*7887SLiane.Praza@Sun.COM 		pg_tmpl = t;
2375*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_orig_inst = inst;
2376*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_orig_svc = svc;
2377*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_snap = snap;
2378*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_is_iter = 1;
2379*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_iter_last = SCF__TMPL_ITER_NONE;
2380*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_pg = pg;
2381*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_populated = 1;
2382*7887SLiane.Praza@Sun.COM 	} else {
2383*7887SLiane.Praza@Sun.COM 		if (t->pt_is_iter != 1) {
2384*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
2385*7887SLiane.Praza@Sun.COM 			return (-1);
2386*7887SLiane.Praza@Sun.COM 		}
2387*7887SLiane.Praza@Sun.COM 		pg_tmpl = t;
2388*7887SLiane.Praza@Sun.COM 		assert(pg_tmpl->pt_pg != NULL);
2389*7887SLiane.Praza@Sun.COM 	}
2390*7887SLiane.Praza@Sun.COM 
2391*7887SLiane.Praza@Sun.COM 	if (pg_tmpl->pt_iter == NULL) {
2392*7887SLiane.Praza@Sun.COM 		pg_tmpl->pt_iter = _get_next_iterator(h, pg_tmpl, snapshot,
2393*7887SLiane.Praza@Sun.COM 		    (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0);
2394*7887SLiane.Praza@Sun.COM 		if (pg_tmpl->pt_iter == NULL) {
2395*7887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
2396*7887SLiane.Praza@Sun.COM 				return (0);
2397*7887SLiane.Praza@Sun.COM 			else
2398*7887SLiane.Praza@Sun.COM 				return (-1);
2399*7887SLiane.Praza@Sun.COM 		}
2400*7887SLiane.Praza@Sun.COM 	}
2401*7887SLiane.Praza@Sun.COM 
2402*7887SLiane.Praza@Sun.COM 	while (found == 0) {
2403*7887SLiane.Praza@Sun.COM 		while ((err = scf_iter_next_pg(pg_tmpl->pt_iter,
2404*7887SLiane.Praza@Sun.COM 		    pg_tmpl->pt_pg)) != 1) {
2405*7887SLiane.Praza@Sun.COM 			if (err == -1) {
2406*7887SLiane.Praza@Sun.COM 				if (ismember(scf_error(), errors_server)) {
2407*7887SLiane.Praza@Sun.COM 					return (-1);
2408*7887SLiane.Praza@Sun.COM 				} else switch (scf_error()) {
2409*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_HANDLE_MISMATCH:
2410*7887SLiane.Praza@Sun.COM 					return (-1);
2411*7887SLiane.Praza@Sun.COM 
2412*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_NOT_SET:
2413*7887SLiane.Praza@Sun.COM 				case SCF_ERROR_INVALID_ARGUMENT:
2414*7887SLiane.Praza@Sun.COM 				default:
2415*7887SLiane.Praza@Sun.COM 					assert(0);
2416*7887SLiane.Praza@Sun.COM 					abort();
2417*7887SLiane.Praza@Sun.COM 				}
2418*7887SLiane.Praza@Sun.COM 			} else if (err == 0)  {
2419*7887SLiane.Praza@Sun.COM 				/* This iteration is done.  Get the next one */
2420*7887SLiane.Praza@Sun.COM 				scf_iter_destroy(pg_tmpl->pt_iter);
2421*7887SLiane.Praza@Sun.COM 				pg_tmpl->pt_iter = _get_next_iterator(h,
2422*7887SLiane.Praza@Sun.COM 				    pg_tmpl, snapshot,
2423*7887SLiane.Praza@Sun.COM 				    (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0);
2424*7887SLiane.Praza@Sun.COM 				if (pg_tmpl->pt_iter == NULL) {
2425*7887SLiane.Praza@Sun.COM 					if (scf_error() == SCF_ERROR_NOT_FOUND)
2426*7887SLiane.Praza@Sun.COM 						return (0);
2427*7887SLiane.Praza@Sun.COM 					else
2428*7887SLiane.Praza@Sun.COM 						return (-1);
2429*7887SLiane.Praza@Sun.COM 				}
2430*7887SLiane.Praza@Sun.COM 				continue;
2431*7887SLiane.Praza@Sun.COM 			} else {
2432*7887SLiane.Praza@Sun.COM 				assert(0);
2433*7887SLiane.Praza@Sun.COM 				abort();
2434*7887SLiane.Praza@Sun.COM 			}
2435*7887SLiane.Praza@Sun.COM 		}
2436*7887SLiane.Praza@Sun.COM 
2437*7887SLiane.Praza@Sun.COM 		/*
2438*7887SLiane.Praza@Sun.COM 		 * Discard pgs which don't exist at the right scoping.  This
2439*7887SLiane.Praza@Sun.COM 		 * check also makes sure that if we're looking at, for
2440*7887SLiane.Praza@Sun.COM 		 * example, svc:/system/svc/restarter:default, that we
2441*7887SLiane.Praza@Sun.COM 		 * don't hand back the same property groups twice.
2442*7887SLiane.Praza@Sun.COM 		 */
2443*7887SLiane.Praza@Sun.COM 		switch (t->pt_iter_last) {
2444*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_INST:
2445*7887SLiane.Praza@Sun.COM 			ret = check_target_match(pg_tmpl->pt_pg,
2446*7887SLiane.Praza@Sun.COM 			    SCF_TM_TARGET_THIS);
2447*7887SLiane.Praza@Sun.COM 			break;
2448*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_RESTARTER:
2449*7887SLiane.Praza@Sun.COM 			ret = check_target_match(pg_tmpl->pt_pg,
2450*7887SLiane.Praza@Sun.COM 			    SCF_TM_TARGET_DELEGATE);
2451*7887SLiane.Praza@Sun.COM 			break;
2452*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_GLOBAL:
2453*7887SLiane.Praza@Sun.COM 			ret = check_target_match(pg_tmpl->pt_pg,
2454*7887SLiane.Praza@Sun.COM 			    SCF_TM_TARGET_ALL);
2455*7887SLiane.Praza@Sun.COM 			break;
2456*7887SLiane.Praza@Sun.COM 		case SCF__TMPL_ITER_NONE:
2457*7887SLiane.Praza@Sun.COM 		default:
2458*7887SLiane.Praza@Sun.COM 			assert(0);
2459*7887SLiane.Praza@Sun.COM 			abort();
2460*7887SLiane.Praza@Sun.COM 		}
2461*7887SLiane.Praza@Sun.COM 
2462*7887SLiane.Praza@Sun.COM 		if (ret != 0)
2463*7887SLiane.Praza@Sun.COM 			continue;
2464*7887SLiane.Praza@Sun.COM 
2465*7887SLiane.Praza@Sun.COM 		/*
2466*7887SLiane.Praza@Sun.COM 		 * If walking only required property groups, check if
2467*7887SLiane.Praza@Sun.COM 		 * the retrieved group is required.
2468*7887SLiane.Praza@Sun.COM 		 */
2469*7887SLiane.Praza@Sun.COM 		if (flags & SCF_PG_TMPL_FLAG_REQUIRED) {
2470*7887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_required(pg_tmpl, &required) == 0) {
2471*7887SLiane.Praza@Sun.COM 				if (required == 0)
2472*7887SLiane.Praza@Sun.COM 					continue;
2473*7887SLiane.Praza@Sun.COM 			} else {
2474*7887SLiane.Praza@Sun.COM 				return (-1);
2475*7887SLiane.Praza@Sun.COM 			}
2476*7887SLiane.Praza@Sun.COM 		}
2477*7887SLiane.Praza@Sun.COM 
2478*7887SLiane.Praza@Sun.COM 		/*
2479*7887SLiane.Praza@Sun.COM 		 * If type != NULL, check if type property matches.  If no
2480*7887SLiane.Praza@Sun.COM 		 * type property exists, consider it a match.
2481*7887SLiane.Praza@Sun.COM 		 */
2482*7887SLiane.Praza@Sun.COM 		if (type != NULL) {
2483*7887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_type(pg_tmpl, &tmpl_type) != -1) {
2484*7887SLiane.Praza@Sun.COM 				if (strcmp(tmpl_type, SCF_TMPL_WILDCARD)
2485*7887SLiane.Praza@Sun.COM 				    == 0 || strcmp(type, tmpl_type) == 0) {
2486*7887SLiane.Praza@Sun.COM 					free(tmpl_type);
2487*7887SLiane.Praza@Sun.COM 					break;
2488*7887SLiane.Praza@Sun.COM 				}
2489*7887SLiane.Praza@Sun.COM 				free(tmpl_type);
2490*7887SLiane.Praza@Sun.COM 			} else if (scf_error() == SCF_ERROR_NOT_FOUND ||
2491*7887SLiane.Praza@Sun.COM 			    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED ||
2492*7887SLiane.Praza@Sun.COM 			    scf_error() == SCF_ERROR_TYPE_MISMATCH) {
2493*7887SLiane.Praza@Sun.COM 				break;
2494*7887SLiane.Praza@Sun.COM 			} else {
2495*7887SLiane.Praza@Sun.COM 				return (-1);
2496*7887SLiane.Praza@Sun.COM 			}
2497*7887SLiane.Praza@Sun.COM 		} else {
2498*7887SLiane.Praza@Sun.COM 			break;
2499*7887SLiane.Praza@Sun.COM 		}
2500*7887SLiane.Praza@Sun.COM 	}
2501*7887SLiane.Praza@Sun.COM 
2502*7887SLiane.Praza@Sun.COM 	return (1);
2503*7887SLiane.Praza@Sun.COM 
2504*7887SLiane.Praza@Sun.COM fail_non_populated:
2505*7887SLiane.Praza@Sun.COM 	scf_service_destroy(svc);
2506*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
2507*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
2508*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
2509*7887SLiane.Praza@Sun.COM 	return (-1);
2510*7887SLiane.Praza@Sun.COM }
2511*7887SLiane.Praza@Sun.COM 
2512*7887SLiane.Praza@Sun.COM void
2513*7887SLiane.Praza@Sun.COM scf_tmpl_pg_destroy(scf_pg_tmpl_t *t)
2514*7887SLiane.Praza@Sun.COM {
2515*7887SLiane.Praza@Sun.COM 	if (t == NULL)
2516*7887SLiane.Praza@Sun.COM 		return;
2517*7887SLiane.Praza@Sun.COM 
2518*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->pt_pg);
2519*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(t->pt_inst);
2520*7887SLiane.Praza@Sun.COM 	if (t->pt_inst != t->pt_orig_inst)
2521*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(t->pt_orig_inst);
2522*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(t->pt_snap);
2523*7887SLiane.Praza@Sun.COM 	scf_service_destroy(t->pt_orig_svc);
2524*7887SLiane.Praza@Sun.COM 	if (t->pt_svc != t->pt_orig_svc)
2525*7887SLiane.Praza@Sun.COM 		scf_service_destroy(t->pt_svc);
2526*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(t->pt_iter);
2527*7887SLiane.Praza@Sun.COM 	free(t);
2528*7887SLiane.Praza@Sun.COM }
2529*7887SLiane.Praza@Sun.COM 
2530*7887SLiane.Praza@Sun.COM void
2531*7887SLiane.Praza@Sun.COM scf_tmpl_pg_reset(scf_pg_tmpl_t *t)
2532*7887SLiane.Praza@Sun.COM {
2533*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->pt_pg);
2534*7887SLiane.Praza@Sun.COM 	t->pt_pg = NULL;
2535*7887SLiane.Praza@Sun.COM 
2536*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(t->pt_inst);
2537*7887SLiane.Praza@Sun.COM 	if (t->pt_inst != t->pt_orig_inst)
2538*7887SLiane.Praza@Sun.COM 		scf_instance_destroy(t->pt_orig_inst);
2539*7887SLiane.Praza@Sun.COM 	t->pt_inst = NULL;
2540*7887SLiane.Praza@Sun.COM 	t->pt_orig_inst = NULL;
2541*7887SLiane.Praza@Sun.COM 
2542*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(t->pt_snap);
2543*7887SLiane.Praza@Sun.COM 	t->pt_snap = NULL;
2544*7887SLiane.Praza@Sun.COM 
2545*7887SLiane.Praza@Sun.COM 	scf_service_destroy(t->pt_orig_svc);
2546*7887SLiane.Praza@Sun.COM 	if (t->pt_svc != t->pt_orig_svc)
2547*7887SLiane.Praza@Sun.COM 		scf_service_destroy(t->pt_svc);
2548*7887SLiane.Praza@Sun.COM 	t->pt_orig_svc = NULL;
2549*7887SLiane.Praza@Sun.COM 	t->pt_svc = NULL;
2550*7887SLiane.Praza@Sun.COM 
2551*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(t->pt_iter);
2552*7887SLiane.Praza@Sun.COM 	t->pt_iter = NULL;
2553*7887SLiane.Praza@Sun.COM 
2554*7887SLiane.Praza@Sun.COM 	t->pt_populated = 0;
2555*7887SLiane.Praza@Sun.COM 	t->pt_is_iter = 0;
2556*7887SLiane.Praza@Sun.COM 	t->pt_iter_last = 0;
2557*7887SLiane.Praza@Sun.COM 
2558*7887SLiane.Praza@Sun.COM 	/* Do not reset t->pt_h. */
2559*7887SLiane.Praza@Sun.COM }
2560*7887SLiane.Praza@Sun.COM 
2561*7887SLiane.Praza@Sun.COM /*
2562*7887SLiane.Praza@Sun.COM  * int scf_tmpl_get_by_prop()
2563*7887SLiane.Praza@Sun.COM  *
2564*7887SLiane.Praza@Sun.COM  * Get the property template given a property group template and property
2565*7887SLiane.Praza@Sun.COM  * name.  No flags are currently defined for this function.
2566*7887SLiane.Praza@Sun.COM  *
2567*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, and sets scf_error():
2568*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2569*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2570*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2571*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2572*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2573*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2574*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2575*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2576*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2577*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
2578*7887SLiane.Praza@Sun.COM  *     Template object matching property doesn't exist in the repository.
2579*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TYPE_MISMATCH
2580*7887SLiane.Praza@Sun.COM  *     Matching template object is the wrong type in the repository.
2581*7887SLiane.Praza@Sun.COM  */
2582*7887SLiane.Praza@Sun.COM int
2583*7887SLiane.Praza@Sun.COM scf_tmpl_get_by_prop(scf_pg_tmpl_t *t, const char *prop,
2584*7887SLiane.Praza@Sun.COM     scf_prop_tmpl_t *prop_tmpl, int flags)
2585*7887SLiane.Praza@Sun.COM {
2586*7887SLiane.Praza@Sun.COM 	char *tmpl_prop_name;
2587*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
2588*7887SLiane.Praza@Sun.COM 	char *pg_type;
2589*7887SLiane.Praza@Sun.COM 	int found = 0;
2590*7887SLiane.Praza@Sun.COM 
2591*7887SLiane.Praza@Sun.COM 	if (flags != 0) {
2592*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
2593*7887SLiane.Praza@Sun.COM 		return (-1);
2594*7887SLiane.Praza@Sun.COM 	}
2595*7887SLiane.Praza@Sun.COM 
2596*7887SLiane.Praza@Sun.COM 	scf_tmpl_prop_reset(prop_tmpl);
2597*7887SLiane.Praza@Sun.COM 	if ((pg = scf_pg_create(scf_pg_handle(t->pt_pg))) == NULL)
2598*7887SLiane.Praza@Sun.COM 		return (-1);
2599*7887SLiane.Praza@Sun.COM 
2600*7887SLiane.Praza@Sun.COM 	tmpl_prop_name = _tmpl_prop_name(prop, t);
2601*7887SLiane.Praza@Sun.COM 	if (tmpl_prop_name == NULL) {
2602*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET);
2603*7887SLiane.Praza@Sun.COM 		return (-1);
2604*7887SLiane.Praza@Sun.COM 	}
2605*7887SLiane.Praza@Sun.COM 
2606*7887SLiane.Praza@Sun.COM 	if (_get_pg(t->pt_svc, t->pt_inst, t->pt_snap,
2607*7887SLiane.Praza@Sun.COM 	    tmpl_prop_name, pg) != 0) {
2608*7887SLiane.Praza@Sun.COM 		if (!ismember(scf_error(), errors_server)) {
2609*7887SLiane.Praza@Sun.COM 			switch (scf_error()) {
2610*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
2611*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
2612*7887SLiane.Praza@Sun.COM 				break;
2613*7887SLiane.Praza@Sun.COM 
2614*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
2615*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
2616*7887SLiane.Praza@Sun.COM 			default:
2617*7887SLiane.Praza@Sun.COM 				assert(0);
2618*7887SLiane.Praza@Sun.COM 				abort();
2619*7887SLiane.Praza@Sun.COM 			}
2620*7887SLiane.Praza@Sun.COM 		}
2621*7887SLiane.Praza@Sun.COM 	} else {
2622*7887SLiane.Praza@Sun.COM 		/*
2623*7887SLiane.Praza@Sun.COM 		 * We've only found a template property group if the type
2624*7887SLiane.Praza@Sun.COM 		 * is correct.
2625*7887SLiane.Praza@Sun.COM 		 */
2626*7887SLiane.Praza@Sun.COM 		if ((pg_type = _scf_get_pg_type(pg)) != NULL &&
2627*7887SLiane.Praza@Sun.COM 		    strcmp(pg_type, SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0)
2628*7887SLiane.Praza@Sun.COM 			found++;
2629*7887SLiane.Praza@Sun.COM 		else
2630*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TYPE_MISMATCH);
2631*7887SLiane.Praza@Sun.COM 
2632*7887SLiane.Praza@Sun.COM 
2633*7887SLiane.Praza@Sun.COM 		free(pg_type);
2634*7887SLiane.Praza@Sun.COM 	}
2635*7887SLiane.Praza@Sun.COM 
2636*7887SLiane.Praza@Sun.COM 	if (found == 0) {
2637*7887SLiane.Praza@Sun.COM 		scf_pg_destroy(pg);
2638*7887SLiane.Praza@Sun.COM 		free(tmpl_prop_name);
2639*7887SLiane.Praza@Sun.COM 		return (-1);
2640*7887SLiane.Praza@Sun.COM 	}
2641*7887SLiane.Praza@Sun.COM 
2642*7887SLiane.Praza@Sun.COM 	prop_tmpl->prt_h = scf_pg_handle(t->pt_pg);
2643*7887SLiane.Praza@Sun.COM 	prop_tmpl->prt_t = t;
2644*7887SLiane.Praza@Sun.COM 	prop_tmpl->prt_pg = pg;
2645*7887SLiane.Praza@Sun.COM 	prop_tmpl->prt_pg_name = tmpl_prop_name;
2646*7887SLiane.Praza@Sun.COM 	prop_tmpl->prt_populated = 1;
2647*7887SLiane.Praza@Sun.COM 
2648*7887SLiane.Praza@Sun.COM 	return (0);
2649*7887SLiane.Praza@Sun.COM }
2650*7887SLiane.Praza@Sun.COM 
2651*7887SLiane.Praza@Sun.COM /*
2652*7887SLiane.Praza@Sun.COM  * scf_prop_tmpl_t *scf_tmpl_prop_create(scf_handle_t *);
2653*7887SLiane.Praza@Sun.COM  *
2654*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT, or
2655*7887SLiane.Praza@Sun.COM  * _NO_MEMORY.
2656*7887SLiane.Praza@Sun.COM  */
2657*7887SLiane.Praza@Sun.COM scf_prop_tmpl_t *
2658*7887SLiane.Praza@Sun.COM scf_tmpl_prop_create(scf_handle_t *handle)
2659*7887SLiane.Praza@Sun.COM {
2660*7887SLiane.Praza@Sun.COM 	scf_prop_tmpl_t *pt;
2661*7887SLiane.Praza@Sun.COM 
2662*7887SLiane.Praza@Sun.COM 	if (handle == NULL) {
2663*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
2664*7887SLiane.Praza@Sun.COM 		return (NULL);
2665*7887SLiane.Praza@Sun.COM 	}
2666*7887SLiane.Praza@Sun.COM 	pt = calloc(1, sizeof (scf_prop_tmpl_t));
2667*7887SLiane.Praza@Sun.COM 	if (pt == NULL)
2668*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2669*7887SLiane.Praza@Sun.COM 	else
2670*7887SLiane.Praza@Sun.COM 		pt->prt_h = handle;
2671*7887SLiane.Praza@Sun.COM 
2672*7887SLiane.Praza@Sun.COM 	return (pt);
2673*7887SLiane.Praza@Sun.COM }
2674*7887SLiane.Praza@Sun.COM 
2675*7887SLiane.Praza@Sun.COM /*
2676*7887SLiane.Praza@Sun.COM  * int scf_tmpl_iter_props()
2677*7887SLiane.Praza@Sun.COM  *
2678*7887SLiane.Praza@Sun.COM  * Iterates over all property templates defined in the specified property
2679*7887SLiane.Praza@Sun.COM  * group template.  The iterator state is stored on the property template
2680*7887SLiane.Praza@Sun.COM  * data structure, and the data structure should be allocated with
2681*7887SLiane.Praza@Sun.COM  * scf_tmpl_prop_create().  To continue the iteration, the previously
2682*7887SLiane.Praza@Sun.COM  * returned structure should be passed in as an argument to this function.
2683*7887SLiane.Praza@Sun.COM  * flags can include SCF_PROP_TMPL_FLAG_REQUIRED.  The function returns
2684*7887SLiane.Praza@Sun.COM  * 1 when a result was found, and 0 when the iteration is complete.
2685*7887SLiane.Praza@Sun.COM  *
2686*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, and sets scf_error():
2687*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2688*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2689*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2690*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2691*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2692*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2693*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2694*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2695*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2696*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
2697*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
2698*7887SLiane.Praza@Sun.COM  *     Template data is invalid.  One of the property templates in this
2699*7887SLiane.Praza@Sun.COM  *     pg_tmpl is malformed.
2700*7887SLiane.Praza@Sun.COM  */
2701*7887SLiane.Praza@Sun.COM int
2702*7887SLiane.Praza@Sun.COM scf_tmpl_iter_props(scf_pg_tmpl_t *t, scf_prop_tmpl_t *pt, int flags)
2703*7887SLiane.Praza@Sun.COM {
2704*7887SLiane.Praza@Sun.COM 	scf_prop_tmpl_t *prop_tmpl;
2705*7887SLiane.Praza@Sun.COM 	char *pg_pat;
2706*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
2707*7887SLiane.Praza@Sun.COM 	int err;
2708*7887SLiane.Praza@Sun.COM 	int ret;
2709*7887SLiane.Praza@Sun.COM 	ssize_t size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
2710*7887SLiane.Praza@Sun.COM 	uint8_t required;
2711*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
2712*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
2713*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
2714*7887SLiane.Praza@Sun.COM 
2715*7887SLiane.Praza@Sun.COM 	assert(size != 0);
2716*7887SLiane.Praza@Sun.COM 	if (t == NULL || pt == NULL) {
2717*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
2718*7887SLiane.Praza@Sun.COM 		return (-1);
2719*7887SLiane.Praza@Sun.COM 	}
2720*7887SLiane.Praza@Sun.COM 
2721*7887SLiane.Praza@Sun.COM 	assert(t->pt_inst == NULL || t->pt_svc == NULL);
2722*7887SLiane.Praza@Sun.COM 	assert(t->pt_inst != NULL || t->pt_svc != NULL);
2723*7887SLiane.Praza@Sun.COM 
2724*7887SLiane.Praza@Sun.COM 	if ((pg_name = malloc(size)) == NULL) {
2725*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
2726*7887SLiane.Praza@Sun.COM 		return (-1);
2727*7887SLiane.Praza@Sun.COM 	}
2728*7887SLiane.Praza@Sun.COM 
2729*7887SLiane.Praza@Sun.COM 	if (pt->prt_populated == 0) {
2730*7887SLiane.Praza@Sun.COM 		if ((h = scf_pg_handle(t->pt_pg)) == NULL)
2731*7887SLiane.Praza@Sun.COM 			goto fail_non_populated;
2732*7887SLiane.Praza@Sun.COM 
2733*7887SLiane.Praza@Sun.COM 		if ((pg = scf_pg_create(h)) == NULL ||
2734*7887SLiane.Praza@Sun.COM 		    (iter = scf_iter_create(h)) == NULL)
2735*7887SLiane.Praza@Sun.COM 			goto fail_non_populated;
2736*7887SLiane.Praza@Sun.COM 
2737*7887SLiane.Praza@Sun.COM 		if (t->pt_inst != NULL)
2738*7887SLiane.Praza@Sun.COM 			err = scf_iter_instance_pgs_typed_composed(iter,
2739*7887SLiane.Praza@Sun.COM 			    t->pt_inst, t->pt_snap,
2740*7887SLiane.Praza@Sun.COM 			    SCF_GROUP_TEMPLATE_PROP_PATTERN);
2741*7887SLiane.Praza@Sun.COM 		else if (t->pt_svc != NULL)
2742*7887SLiane.Praza@Sun.COM 			err = scf_iter_service_pgs_typed(iter, t->pt_svc,
2743*7887SLiane.Praza@Sun.COM 			    SCF_GROUP_TEMPLATE_PROP_PATTERN);
2744*7887SLiane.Praza@Sun.COM 
2745*7887SLiane.Praza@Sun.COM 		if (err != 0) {
2746*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
2747*7887SLiane.Praza@Sun.COM 				goto fail_non_populated;
2748*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
2749*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
2750*7887SLiane.Praza@Sun.COM 				goto fail_non_populated;
2751*7887SLiane.Praza@Sun.COM 
2752*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
2753*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
2754*7887SLiane.Praza@Sun.COM 			default:
2755*7887SLiane.Praza@Sun.COM 				assert(0);
2756*7887SLiane.Praza@Sun.COM 				abort();
2757*7887SLiane.Praza@Sun.COM 			}
2758*7887SLiane.Praza@Sun.COM 
2759*7887SLiane.Praza@Sun.COM 		}
2760*7887SLiane.Praza@Sun.COM 		prop_tmpl = pt;
2761*7887SLiane.Praza@Sun.COM 		prop_tmpl->prt_t = t;
2762*7887SLiane.Praza@Sun.COM 		prop_tmpl->prt_populated = 1;
2763*7887SLiane.Praza@Sun.COM 		prop_tmpl->prt_pg = pg;
2764*7887SLiane.Praza@Sun.COM 		prop_tmpl->prt_iter = iter;
2765*7887SLiane.Praza@Sun.COM 	} else {
2766*7887SLiane.Praza@Sun.COM 		prop_tmpl = pt;
2767*7887SLiane.Praza@Sun.COM 	}
2768*7887SLiane.Praza@Sun.COM 
2769*7887SLiane.Praza@Sun.COM 	while ((err = scf_iter_next_pg(prop_tmpl->prt_iter,
2770*7887SLiane.Praza@Sun.COM 	    prop_tmpl->prt_pg)) > 0) {
2771*7887SLiane.Praza@Sun.COM 		/*
2772*7887SLiane.Praza@Sun.COM 		 * Check if the name matches the appropriate property
2773*7887SLiane.Praza@Sun.COM 		 * group template name.
2774*7887SLiane.Praza@Sun.COM 		 */
2775*7887SLiane.Praza@Sun.COM 		pg_pat = _scf_read_single_astring_from_pg(prop_tmpl->prt_pg,
2776*7887SLiane.Praza@Sun.COM 		    SCF_PROPERTY_TM_PG_PATTERN);
2777*7887SLiane.Praza@Sun.COM 		if (pg_pat == NULL) {
2778*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
2779*7887SLiane.Praza@Sun.COM 				uu_free(pg_name);
2780*7887SLiane.Praza@Sun.COM 				return (-1);
2781*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
2782*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
2783*7887SLiane.Praza@Sun.COM 				continue;
2784*7887SLiane.Praza@Sun.COM 
2785*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
2786*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_TYPE_MISMATCH:
2787*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
2788*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
2789*7887SLiane.Praza@Sun.COM 				free(pg_name);
2790*7887SLiane.Praza@Sun.COM 				return (-1);
2791*7887SLiane.Praza@Sun.COM 
2792*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
2793*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
2794*7887SLiane.Praza@Sun.COM 			default:
2795*7887SLiane.Praza@Sun.COM 				assert(0);
2796*7887SLiane.Praza@Sun.COM 				abort();
2797*7887SLiane.Praza@Sun.COM 			}
2798*7887SLiane.Praza@Sun.COM 		}
2799*7887SLiane.Praza@Sun.COM 		if ((ret = scf_pg_get_name(t->pt_pg, pg_name, size)) <= 0) {
2800*7887SLiane.Praza@Sun.COM 			free(pg_pat);
2801*7887SLiane.Praza@Sun.COM 			if (ret == 0)
2802*7887SLiane.Praza@Sun.COM 				continue;
2803*7887SLiane.Praza@Sun.COM 
2804*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
2805*7887SLiane.Praza@Sun.COM 				free(pg_name);
2806*7887SLiane.Praza@Sun.COM 				return (-1);
2807*7887SLiane.Praza@Sun.COM 			} else {
2808*7887SLiane.Praza@Sun.COM 				assert(0);
2809*7887SLiane.Praza@Sun.COM 				abort();
2810*7887SLiane.Praza@Sun.COM 			}
2811*7887SLiane.Praza@Sun.COM 		}
2812*7887SLiane.Praza@Sun.COM 		if (strcmp(pg_pat, pg_name) != 0) {
2813*7887SLiane.Praza@Sun.COM 			free(pg_pat);
2814*7887SLiane.Praza@Sun.COM 			continue;
2815*7887SLiane.Praza@Sun.COM 		}
2816*7887SLiane.Praza@Sun.COM 		free(pg_pat);
2817*7887SLiane.Praza@Sun.COM 
2818*7887SLiane.Praza@Sun.COM 		/*
2819*7887SLiane.Praza@Sun.COM 		 * If walking only required properties, check if
2820*7887SLiane.Praza@Sun.COM 		 * the retrieved property is required.
2821*7887SLiane.Praza@Sun.COM 		 */
2822*7887SLiane.Praza@Sun.COM 		if (flags & SCF_PROP_TMPL_FLAG_REQUIRED) {
2823*7887SLiane.Praza@Sun.COM 			if (scf_tmpl_prop_required(prop_tmpl, &required) == 0) {
2824*7887SLiane.Praza@Sun.COM 				if (required == 0)
2825*7887SLiane.Praza@Sun.COM 					continue;
2826*7887SLiane.Praza@Sun.COM 			} else {
2827*7887SLiane.Praza@Sun.COM 				free(pg_name);
2828*7887SLiane.Praza@Sun.COM 				return (-1);
2829*7887SLiane.Praza@Sun.COM 			}
2830*7887SLiane.Praza@Sun.COM 		}
2831*7887SLiane.Praza@Sun.COM 		free(pg_name);
2832*7887SLiane.Praza@Sun.COM 		return (0);
2833*7887SLiane.Praza@Sun.COM 	}
2834*7887SLiane.Praza@Sun.COM 
2835*7887SLiane.Praza@Sun.COM 	if (err == -1) {
2836*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
2837*7887SLiane.Praza@Sun.COM 			free(pg_name);
2838*7887SLiane.Praza@Sun.COM 			return (-1);
2839*7887SLiane.Praza@Sun.COM 		} else {
2840*7887SLiane.Praza@Sun.COM 			assert(0);
2841*7887SLiane.Praza@Sun.COM 			abort();
2842*7887SLiane.Praza@Sun.COM 		}
2843*7887SLiane.Praza@Sun.COM 	} else if (err == 0)  {
2844*7887SLiane.Praza@Sun.COM 		scf_iter_destroy(prop_tmpl->prt_iter);
2845*7887SLiane.Praza@Sun.COM 		prop_tmpl->prt_iter = NULL;
2846*7887SLiane.Praza@Sun.COM 		prop_tmpl->prt_populated = 0;
2847*7887SLiane.Praza@Sun.COM 	}
2848*7887SLiane.Praza@Sun.COM 	free(pg_name);
2849*7887SLiane.Praza@Sun.COM 
2850*7887SLiane.Praza@Sun.COM 	return (1);
2851*7887SLiane.Praza@Sun.COM 
2852*7887SLiane.Praza@Sun.COM fail_non_populated:
2853*7887SLiane.Praza@Sun.COM 	free(pg_name);
2854*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
2855*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
2856*7887SLiane.Praza@Sun.COM 	return (-1);
2857*7887SLiane.Praza@Sun.COM }
2858*7887SLiane.Praza@Sun.COM 
2859*7887SLiane.Praza@Sun.COM void
2860*7887SLiane.Praza@Sun.COM scf_tmpl_prop_destroy(scf_prop_tmpl_t *t)
2861*7887SLiane.Praza@Sun.COM {
2862*7887SLiane.Praza@Sun.COM 	if (t == NULL)
2863*7887SLiane.Praza@Sun.COM 		return;
2864*7887SLiane.Praza@Sun.COM 
2865*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->prt_pg);
2866*7887SLiane.Praza@Sun.COM 	free(t->prt_pg_name);
2867*7887SLiane.Praza@Sun.COM 	free(t->prt_iter);
2868*7887SLiane.Praza@Sun.COM 	free(t);
2869*7887SLiane.Praza@Sun.COM }
2870*7887SLiane.Praza@Sun.COM 
2871*7887SLiane.Praza@Sun.COM void
2872*7887SLiane.Praza@Sun.COM scf_tmpl_prop_reset(scf_prop_tmpl_t *t)
2873*7887SLiane.Praza@Sun.COM {
2874*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(t->prt_pg);
2875*7887SLiane.Praza@Sun.COM 	t->prt_pg = NULL;
2876*7887SLiane.Praza@Sun.COM 
2877*7887SLiane.Praza@Sun.COM 	free(t->prt_pg_name);
2878*7887SLiane.Praza@Sun.COM 	t->prt_pg_name = NULL;
2879*7887SLiane.Praza@Sun.COM 
2880*7887SLiane.Praza@Sun.COM 	free(t->prt_iter);
2881*7887SLiane.Praza@Sun.COM 	t->prt_iter = NULL;
2882*7887SLiane.Praza@Sun.COM 
2883*7887SLiane.Praza@Sun.COM 	t->prt_populated = 0;
2884*7887SLiane.Praza@Sun.COM 	t->prt_h = NULL;
2885*7887SLiane.Praza@Sun.COM 	t->prt_t = NULL;
2886*7887SLiane.Praza@Sun.COM }
2887*7887SLiane.Praza@Sun.COM 
2888*7887SLiane.Praza@Sun.COM /*
2889*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
2890*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2891*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2892*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2893*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2894*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2895*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2896*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2897*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2898*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
2899*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
2900*7887SLiane.Praza@Sun.COM  *     The name of the template property group (the pname property) has
2901*7887SLiane.Praza@Sun.COM  *     an improper repository format and is not type astring or has
2902*7887SLiane.Praza@Sun.COM  *     more than one value.
2903*7887SLiane.Praza@Sun.COM  */
2904*7887SLiane.Praza@Sun.COM ssize_t
2905*7887SLiane.Praza@Sun.COM scf_tmpl_pg_name(const scf_pg_tmpl_t *t, char **out)
2906*7887SLiane.Praza@Sun.COM {
2907*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_NAME, out));
2908*7887SLiane.Praza@Sun.COM }
2909*7887SLiane.Praza@Sun.COM 
2910*7887SLiane.Praza@Sun.COM /*
2911*7887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed
2912*7887SLiane.Praza@Sun.COM  *
2913*7887SLiane.Praza@Sun.COM  * Returns NULL on failure, sets scf_error() to:
2914*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2915*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2916*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2917*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2918*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2919*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2920*7887SLiane.Praza@Sun.COM  *     name not a valid property name
2921*7887SLiane.Praza@Sun.COM  *     name and locale are too long to make a property name
2922*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2923*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2924*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2925*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
2926*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
2927*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
2928*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
2929*7887SLiane.Praza@Sun.COM  */
2930*7887SLiane.Praza@Sun.COM static char *
2931*7887SLiane.Praza@Sun.COM _read_localized_astring_from_pg(scf_propertygroup_t *pg, const char *name,
2932*7887SLiane.Praza@Sun.COM     const char *locale)
2933*7887SLiane.Praza@Sun.COM {
2934*7887SLiane.Praza@Sun.COM 	char *str;
2935*7887SLiane.Praza@Sun.COM 	char *lname_prop;
2936*7887SLiane.Praza@Sun.COM 
2937*7887SLiane.Praza@Sun.COM 	str = _add_locale_to_name(name, locale);
2938*7887SLiane.Praza@Sun.COM 	if (str == NULL)
2939*7887SLiane.Praza@Sun.COM 		return (NULL);
2940*7887SLiane.Praza@Sun.COM 	lname_prop = _scf_read_single_astring_from_pg(pg, str);
2941*7887SLiane.Praza@Sun.COM 	if (lname_prop == NULL) {
2942*7887SLiane.Praza@Sun.COM 		free(str);
2943*7887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND)
2944*7887SLiane.Praza@Sun.COM 			return (NULL);
2945*7887SLiane.Praza@Sun.COM 		str = _add_locale_to_name(name, "C");
2946*7887SLiane.Praza@Sun.COM 		if (str == NULL)
2947*7887SLiane.Praza@Sun.COM 			return (NULL);
2948*7887SLiane.Praza@Sun.COM 		lname_prop = _scf_read_single_astring_from_pg(pg, str);
2949*7887SLiane.Praza@Sun.COM 	}
2950*7887SLiane.Praza@Sun.COM 	free(str);
2951*7887SLiane.Praza@Sun.COM 	if (lname_prop == NULL) {
2952*7887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_TYPE_MISMATCH ||
2953*7887SLiane.Praza@Sun.COM 		    scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
2954*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
2955*7887SLiane.Praza@Sun.COM 	}
2956*7887SLiane.Praza@Sun.COM 	return (lname_prop);
2957*7887SLiane.Praza@Sun.COM }
2958*7887SLiane.Praza@Sun.COM 
2959*7887SLiane.Praza@Sun.COM /*
2960*7887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed
2961*7887SLiane.Praza@Sun.COM  *
2962*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
2963*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2964*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2965*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2966*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2967*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2968*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2969*7887SLiane.Praza@Sun.COM  *     locale is too long to make a valid property name
2970*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
2971*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
2972*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
2973*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
2974*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
2975*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
2976*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
2977*7887SLiane.Praza@Sun.COM  */
2978*7887SLiane.Praza@Sun.COM ssize_t
2979*7887SLiane.Praza@Sun.COM scf_tmpl_pg_common_name(const scf_pg_tmpl_t *t, const char *locale, char **out)
2980*7887SLiane.Praza@Sun.COM {
2981*7887SLiane.Praza@Sun.COM 	assert(out != NULL);
2982*7887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->pt_pg,
2983*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL)
2984*7887SLiane.Praza@Sun.COM 		return (-1);
2985*7887SLiane.Praza@Sun.COM 
2986*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
2987*7887SLiane.Praza@Sun.COM }
2988*7887SLiane.Praza@Sun.COM 
2989*7887SLiane.Praza@Sun.COM /*
2990*7887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed
2991*7887SLiane.Praza@Sun.COM  *
2992*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
2993*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
2994*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
2995*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
2996*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
2997*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
2998*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
2999*7887SLiane.Praza@Sun.COM  *     locale is too long to make a valid property name
3000*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3001*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3002*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3003*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3004*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3005*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3006*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3007*7887SLiane.Praza@Sun.COM  */
3008*7887SLiane.Praza@Sun.COM ssize_t
3009*7887SLiane.Praza@Sun.COM scf_tmpl_pg_description(const scf_pg_tmpl_t *t, const char *locale, char **out)
3010*7887SLiane.Praza@Sun.COM {
3011*7887SLiane.Praza@Sun.COM 	assert(out != NULL);
3012*7887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->pt_pg,
3013*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL)
3014*7887SLiane.Praza@Sun.COM 		return (-1);
3015*7887SLiane.Praza@Sun.COM 
3016*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
3017*7887SLiane.Praza@Sun.COM }
3018*7887SLiane.Praza@Sun.COM 
3019*7887SLiane.Praza@Sun.COM /*
3020*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3021*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3022*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3023*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3024*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3025*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3026*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3027*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3028*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3029*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3030*7887SLiane.Praza@Sun.COM  *     'type' property doesn't exist or exists and has no value.
3031*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3032*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3033*7887SLiane.Praza@Sun.COM  *     'type' property is not SCF_TYPE_ASTRING or has more than one value.
3034*7887SLiane.Praza@Sun.COM  */
3035*7887SLiane.Praza@Sun.COM ssize_t
3036*7887SLiane.Praza@Sun.COM scf_tmpl_pg_type(const scf_pg_tmpl_t *t, char **out)
3037*7887SLiane.Praza@Sun.COM {
3038*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_TYPE, out));
3039*7887SLiane.Praza@Sun.COM }
3040*7887SLiane.Praza@Sun.COM 
3041*7887SLiane.Praza@Sun.COM /*
3042*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
3043*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3044*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3045*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3046*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3047*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3048*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3049*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3050*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3051*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3052*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3053*7887SLiane.Praza@Sun.COM  *     required property is not SCF_TYPE_BOOLEAN or has more than one value.
3054*7887SLiane.Praza@Sun.COM  */
3055*7887SLiane.Praza@Sun.COM int
3056*7887SLiane.Praza@Sun.COM scf_tmpl_pg_required(const scf_pg_tmpl_t *t, uint8_t *out)
3057*7887SLiane.Praza@Sun.COM {
3058*7887SLiane.Praza@Sun.COM 
3059*7887SLiane.Praza@Sun.COM 	if (_read_single_boolean_from_pg(t->pt_pg, SCF_PROPERTY_TM_REQUIRED,
3060*7887SLiane.Praza@Sun.COM 	    out) == -1) {
3061*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3062*7887SLiane.Praza@Sun.COM 			return (-1);
3063*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3064*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3065*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3066*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3067*7887SLiane.Praza@Sun.COM 			return (-1);
3068*7887SLiane.Praza@Sun.COM 
3069*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3070*7887SLiane.Praza@Sun.COM 			*out = 0;
3071*7887SLiane.Praza@Sun.COM 			return (0);
3072*7887SLiane.Praza@Sun.COM 
3073*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3074*7887SLiane.Praza@Sun.COM 		default:
3075*7887SLiane.Praza@Sun.COM 			assert(0);
3076*7887SLiane.Praza@Sun.COM 			abort();
3077*7887SLiane.Praza@Sun.COM 		}
3078*7887SLiane.Praza@Sun.COM 	}
3079*7887SLiane.Praza@Sun.COM 
3080*7887SLiane.Praza@Sun.COM 	return (0);
3081*7887SLiane.Praza@Sun.COM }
3082*7887SLiane.Praza@Sun.COM 
3083*7887SLiane.Praza@Sun.COM /*
3084*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3085*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3086*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3087*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3088*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3089*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3090*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3091*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3092*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3093*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3094*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3095*7887SLiane.Praza@Sun.COM  *     target property is not SCF_TYPE_ASTRING or has more than one value.
3096*7887SLiane.Praza@Sun.COM  */
3097*7887SLiane.Praza@Sun.COM ssize_t
3098*7887SLiane.Praza@Sun.COM scf_tmpl_pg_target(const scf_pg_tmpl_t *t, char **out)
3099*7887SLiane.Praza@Sun.COM {
3100*7887SLiane.Praza@Sun.COM 	*out = _scf_read_single_astring_from_pg(t->pt_pg,
3101*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TARGET);
3102*7887SLiane.Praza@Sun.COM 
3103*7887SLiane.Praza@Sun.COM 	if (*out == NULL) {
3104*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3105*7887SLiane.Praza@Sun.COM 			return (-1);
3106*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3107*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3108*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3109*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3110*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3111*7887SLiane.Praza@Sun.COM 			return (-1);
3112*7887SLiane.Praza@Sun.COM 
3113*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3114*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3115*7887SLiane.Praza@Sun.COM 		default:
3116*7887SLiane.Praza@Sun.COM 			assert(0);
3117*7887SLiane.Praza@Sun.COM 			abort();
3118*7887SLiane.Praza@Sun.COM 		}
3119*7887SLiane.Praza@Sun.COM 	}
3120*7887SLiane.Praza@Sun.COM 
3121*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
3122*7887SLiane.Praza@Sun.COM }
3123*7887SLiane.Praza@Sun.COM 
3124*7887SLiane.Praza@Sun.COM /*
3125*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3126*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3127*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3128*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3129*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3130*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3131*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3132*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3133*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3134*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3135*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3136*7887SLiane.Praza@Sun.COM  */
3137*7887SLiane.Praza@Sun.COM ssize_t
3138*7887SLiane.Praza@Sun.COM scf_tmpl_prop_name(const scf_prop_tmpl_t *t, char **out)
3139*7887SLiane.Praza@Sun.COM {
3140*7887SLiane.Praza@Sun.COM 	*out = _scf_read_single_astring_from_pg(t->prt_pg,
3141*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_NAME);
3142*7887SLiane.Praza@Sun.COM 
3143*7887SLiane.Praza@Sun.COM 	if (*out != NULL && *out[0] == '\0') {
3144*7887SLiane.Praza@Sun.COM 		free(*out);
3145*7887SLiane.Praza@Sun.COM 		*out = NULL;
3146*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3147*7887SLiane.Praza@Sun.COM 	}
3148*7887SLiane.Praza@Sun.COM 	if (*out == NULL) {
3149*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3150*7887SLiane.Praza@Sun.COM 			return (-1);
3151*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3152*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3153*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3154*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TEMPLATE_INVALID:
3155*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3156*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3157*7887SLiane.Praza@Sun.COM 			return (-1);
3158*7887SLiane.Praza@Sun.COM 
3159*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3160*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3161*7887SLiane.Praza@Sun.COM 		default:
3162*7887SLiane.Praza@Sun.COM 			assert(0);
3163*7887SLiane.Praza@Sun.COM 			abort();
3164*7887SLiane.Praza@Sun.COM 		}
3165*7887SLiane.Praza@Sun.COM 	}
3166*7887SLiane.Praza@Sun.COM 
3167*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
3168*7887SLiane.Praza@Sun.COM }
3169*7887SLiane.Praza@Sun.COM 
3170*7887SLiane.Praza@Sun.COM /*
3171*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3172*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3173*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3174*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3175*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3176*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3177*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3178*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3179*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3180*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3181*7887SLiane.Praza@Sun.COM  *     'type' property doesn't exist or exists and has no value.
3182*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3183*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3184*7887SLiane.Praza@Sun.COM  *     'type' property is not SCF_TYPE_ASTRING, has more than one value,
3185*7887SLiane.Praza@Sun.COM  *     is SCF_TYPE_INVALID, or is the empty string.
3186*7887SLiane.Praza@Sun.COM  */
3187*7887SLiane.Praza@Sun.COM int
3188*7887SLiane.Praza@Sun.COM scf_tmpl_prop_type(const scf_prop_tmpl_t *t, scf_type_t *out)
3189*7887SLiane.Praza@Sun.COM {
3190*7887SLiane.Praza@Sun.COM 	char *type;
3191*7887SLiane.Praza@Sun.COM 
3192*7887SLiane.Praza@Sun.COM 	type = _scf_read_single_astring_from_pg(t->prt_pg,
3193*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_TYPE);
3194*7887SLiane.Praza@Sun.COM 	if (type != NULL && type[0] == '\0') {
3195*7887SLiane.Praza@Sun.COM 		free(type);
3196*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
3197*7887SLiane.Praza@Sun.COM 		return (-1);
3198*7887SLiane.Praza@Sun.COM 	}
3199*7887SLiane.Praza@Sun.COM 	if (type == NULL) {
3200*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3201*7887SLiane.Praza@Sun.COM 			return (-1);
3202*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3203*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3204*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3205*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3206*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
3207*7887SLiane.Praza@Sun.COM 
3208*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3209*7887SLiane.Praza@Sun.COM 			return (-1);
3210*7887SLiane.Praza@Sun.COM 
3211*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3212*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3213*7887SLiane.Praza@Sun.COM 		default:
3214*7887SLiane.Praza@Sun.COM 			assert(0);
3215*7887SLiane.Praza@Sun.COM 			abort();
3216*7887SLiane.Praza@Sun.COM 		}
3217*7887SLiane.Praza@Sun.COM 	}
3218*7887SLiane.Praza@Sun.COM 
3219*7887SLiane.Praza@Sun.COM 	*out = scf_string_to_type(type);
3220*7887SLiane.Praza@Sun.COM 	free(type);
3221*7887SLiane.Praza@Sun.COM 
3222*7887SLiane.Praza@Sun.COM 	if (*out == SCF_TYPE_INVALID) {
3223*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3224*7887SLiane.Praza@Sun.COM 		return (-1);
3225*7887SLiane.Praza@Sun.COM 	}
3226*7887SLiane.Praza@Sun.COM 
3227*7887SLiane.Praza@Sun.COM 	return (0);
3228*7887SLiane.Praza@Sun.COM }
3229*7887SLiane.Praza@Sun.COM 
3230*7887SLiane.Praza@Sun.COM /*
3231*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
3232*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3233*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3234*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3235*7887SLiane.Praza@Sun.COM  *    Property group which represents t was deleted.
3236*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3237*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3238*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3239*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3240*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3241*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3242*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3243*7887SLiane.Praza@Sun.COM  *     required property is not SCF_TYPE_ASTRING has more than one value.
3244*7887SLiane.Praza@Sun.COM  */
3245*7887SLiane.Praza@Sun.COM int
3246*7887SLiane.Praza@Sun.COM scf_tmpl_prop_required(const scf_prop_tmpl_t *t, uint8_t *out)
3247*7887SLiane.Praza@Sun.COM {
3248*7887SLiane.Praza@Sun.COM 	if (_read_single_boolean_from_pg(t->prt_pg, SCF_PROPERTY_TM_REQUIRED,
3249*7887SLiane.Praza@Sun.COM 	    out) == -1) {
3250*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3251*7887SLiane.Praza@Sun.COM 			return (-1);
3252*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3253*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3254*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3255*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3256*7887SLiane.Praza@Sun.COM 			return (-1);
3257*7887SLiane.Praza@Sun.COM 
3258*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3259*7887SLiane.Praza@Sun.COM 			*out = 0;
3260*7887SLiane.Praza@Sun.COM 			return (0);
3261*7887SLiane.Praza@Sun.COM 
3262*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3263*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3264*7887SLiane.Praza@Sun.COM 		default:
3265*7887SLiane.Praza@Sun.COM 			assert(0);
3266*7887SLiane.Praza@Sun.COM 			abort();
3267*7887SLiane.Praza@Sun.COM 		}
3268*7887SLiane.Praza@Sun.COM 	}
3269*7887SLiane.Praza@Sun.COM 
3270*7887SLiane.Praza@Sun.COM 	return (0);
3271*7887SLiane.Praza@Sun.COM }
3272*7887SLiane.Praza@Sun.COM 
3273*7887SLiane.Praza@Sun.COM /*
3274*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3275*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3276*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3277*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3278*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3279*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3280*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3281*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3282*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3283*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3284*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3285*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
3286*7887SLiane.Praza@Sun.COM  *     locale is too long to make a property name
3287*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3288*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3289*7887SLiane.Praza@Sun.COM  *     common_name property is not SCF_TYPE_ASTRING has more than one value.
3290*7887SLiane.Praza@Sun.COM  */
3291*7887SLiane.Praza@Sun.COM ssize_t
3292*7887SLiane.Praza@Sun.COM scf_tmpl_prop_common_name(const scf_prop_tmpl_t *t, const char *locale,
3293*7887SLiane.Praza@Sun.COM     char **out)
3294*7887SLiane.Praza@Sun.COM {
3295*7887SLiane.Praza@Sun.COM 	assert(out != NULL);
3296*7887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->prt_pg,
3297*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL)
3298*7887SLiane.Praza@Sun.COM 		return (-1);
3299*7887SLiane.Praza@Sun.COM 
3300*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
3301*7887SLiane.Praza@Sun.COM }
3302*7887SLiane.Praza@Sun.COM 
3303*7887SLiane.Praza@Sun.COM /*
3304*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3305*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3306*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3307*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3308*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3309*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3310*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3311*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3312*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3313*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3314*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3315*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
3316*7887SLiane.Praza@Sun.COM  *     locale is too long to make a property name
3317*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3318*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3319*7887SLiane.Praza@Sun.COM  *     description property is not SCF_TYPE_ASTRING has more than one value.
3320*7887SLiane.Praza@Sun.COM  */
3321*7887SLiane.Praza@Sun.COM ssize_t
3322*7887SLiane.Praza@Sun.COM scf_tmpl_prop_description(const scf_prop_tmpl_t *t, const char *locale,
3323*7887SLiane.Praza@Sun.COM     char **out)
3324*7887SLiane.Praza@Sun.COM {
3325*7887SLiane.Praza@Sun.COM 	assert(out != NULL);
3326*7887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->prt_pg,
3327*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL)
3328*7887SLiane.Praza@Sun.COM 		return (-1);
3329*7887SLiane.Praza@Sun.COM 
3330*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
3331*7887SLiane.Praza@Sun.COM }
3332*7887SLiane.Praza@Sun.COM 
3333*7887SLiane.Praza@Sun.COM /*
3334*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3335*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3336*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3337*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3338*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3339*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3340*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3341*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3342*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3343*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3344*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3345*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
3346*7887SLiane.Praza@Sun.COM  *     locale is too long to make a property name
3347*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3348*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3349*7887SLiane.Praza@Sun.COM  *     units property is not SCF_TYPE_ASTRING has more than one value.
3350*7887SLiane.Praza@Sun.COM  */
3351*7887SLiane.Praza@Sun.COM ssize_t
3352*7887SLiane.Praza@Sun.COM scf_tmpl_prop_units(const scf_prop_tmpl_t *t, const char *locale, char **out)
3353*7887SLiane.Praza@Sun.COM {
3354*7887SLiane.Praza@Sun.COM 	assert(out != NULL);
3355*7887SLiane.Praza@Sun.COM 	if ((*out = _read_localized_astring_from_pg(t->prt_pg,
3356*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_UNITS_PREFIX, locale)) == NULL)
3357*7887SLiane.Praza@Sun.COM 		return (-1);
3358*7887SLiane.Praza@Sun.COM 
3359*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
3360*7887SLiane.Praza@Sun.COM }
3361*7887SLiane.Praza@Sun.COM 
3362*7887SLiane.Praza@Sun.COM /*
3363*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3364*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3365*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3366*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3367*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3368*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3369*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3370*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3371*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3372*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3373*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3374*7887SLiane.Praza@Sun.COM  *     visibility property is not SCF_TYPE_ASTRING has more than one value.
3375*7887SLiane.Praza@Sun.COM  */
3376*7887SLiane.Praza@Sun.COM int
3377*7887SLiane.Praza@Sun.COM scf_tmpl_prop_visibility(const scf_prop_tmpl_t *t, uint8_t *out)
3378*7887SLiane.Praza@Sun.COM {
3379*7887SLiane.Praza@Sun.COM 	char *visibility;
3380*7887SLiane.Praza@Sun.COM 
3381*7887SLiane.Praza@Sun.COM 	visibility = _scf_read_single_astring_from_pg(t->prt_pg,
3382*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_VISIBILITY);
3383*7887SLiane.Praza@Sun.COM 	if (visibility == NULL) {
3384*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3385*7887SLiane.Praza@Sun.COM 			return (-1);
3386*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3387*7887SLiane.Praza@Sun.COM 		/* prop doesn't exist we take the default value */
3388*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3389*7887SLiane.Praza@Sun.COM 			*out = SCF_TMPL_VISIBILITY_READWRITE;
3390*7887SLiane.Praza@Sun.COM 			return (0);
3391*7887SLiane.Praza@Sun.COM 
3392*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3393*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3394*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3395*7887SLiane.Praza@Sun.COM 			return (-1);
3396*7887SLiane.Praza@Sun.COM 
3397*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3398*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3399*7887SLiane.Praza@Sun.COM 		default:
3400*7887SLiane.Praza@Sun.COM 			assert(0);
3401*7887SLiane.Praza@Sun.COM 			abort();
3402*7887SLiane.Praza@Sun.COM 		}
3403*7887SLiane.Praza@Sun.COM 	} else if (strcmp(visibility, SCF_TM_VISIBILITY_READWRITE) == 0) {
3404*7887SLiane.Praza@Sun.COM 		*out = SCF_TMPL_VISIBILITY_READWRITE;
3405*7887SLiane.Praza@Sun.COM 	} else if (strcmp(visibility, SCF_TM_VISIBILITY_HIDDEN) == 0) {
3406*7887SLiane.Praza@Sun.COM 		*out = SCF_TMPL_VISIBILITY_HIDDEN;
3407*7887SLiane.Praza@Sun.COM 	} else if (strcmp(visibility, SCF_TM_VISIBILITY_READONLY) == 0) {
3408*7887SLiane.Praza@Sun.COM 		*out = SCF_TMPL_VISIBILITY_READONLY;
3409*7887SLiane.Praza@Sun.COM 	} else {
3410*7887SLiane.Praza@Sun.COM 		free(visibility);
3411*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3412*7887SLiane.Praza@Sun.COM 		return (-1);
3413*7887SLiane.Praza@Sun.COM 	}
3414*7887SLiane.Praza@Sun.COM 
3415*7887SLiane.Praza@Sun.COM 	free(visibility);
3416*7887SLiane.Praza@Sun.COM 	return (0);
3417*7887SLiane.Praza@Sun.COM }
3418*7887SLiane.Praza@Sun.COM 
3419*7887SLiane.Praza@Sun.COM /*
3420*7887SLiane.Praza@Sun.COM  * Return an allocated string containing the value that must be freed
3421*7887SLiane.Praza@Sun.COM  * with free().
3422*7887SLiane.Praza@Sun.COM  *
3423*7887SLiane.Praza@Sun.COM  * On error set scf_error() _NO_MEMORY, or _NOT_SET (val has not been set
3424*7887SLiane.Praza@Sun.COM  * to a value).
3425*7887SLiane.Praza@Sun.COM  */
3426*7887SLiane.Praza@Sun.COM static char *
3427*7887SLiane.Praza@Sun.COM _scf_value_get_as_string(scf_value_t *val)
3428*7887SLiane.Praza@Sun.COM {
3429*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
3430*7887SLiane.Praza@Sun.COM 	char *buf = malloc(sz);
3431*7887SLiane.Praza@Sun.COM 
3432*7887SLiane.Praza@Sun.COM 	if (buf == NULL) {
3433*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
3434*7887SLiane.Praza@Sun.COM 	} else if (scf_value_get_as_string(val, buf, sz) == -1) {
3435*7887SLiane.Praza@Sun.COM 		free(buf);
3436*7887SLiane.Praza@Sun.COM 		buf = NULL;
3437*7887SLiane.Praza@Sun.COM 	}
3438*7887SLiane.Praza@Sun.COM 
3439*7887SLiane.Praza@Sun.COM 	return (buf);
3440*7887SLiane.Praza@Sun.COM }
3441*7887SLiane.Praza@Sun.COM 
3442*7887SLiane.Praza@Sun.COM /*
3443*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
3444*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3445*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3446*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3447*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3448*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3449*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3450*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3451*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3452*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3453*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3454*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3455*7887SLiane.Praza@Sun.COM  */
3456*7887SLiane.Praza@Sun.COM int
3457*7887SLiane.Praza@Sun.COM scf_tmpl_prop_cardinality(const scf_prop_tmpl_t *t, uint64_t *min,
3458*7887SLiane.Praza@Sun.COM     uint64_t *max)
3459*7887SLiane.Praza@Sun.COM {
3460*7887SLiane.Praza@Sun.COM 	scf_value_t *val_min = NULL;
3461*7887SLiane.Praza@Sun.COM 	scf_value_t *val_max = NULL;
3462*7887SLiane.Praza@Sun.COM 	int ret = 0;
3463*7887SLiane.Praza@Sun.COM 
3464*7887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(t->prt_pg,
3465*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CARDINALITY_MIN, &val_min) == 0) {
3466*7887SLiane.Praza@Sun.COM 		if (scf_value_get_count(val_min, min) < 0)
3467*7887SLiane.Praza@Sun.COM 			goto error;
3468*7887SLiane.Praza@Sun.COM 	} else {
3469*7887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND)
3470*7887SLiane.Praza@Sun.COM 			*min = 0;
3471*7887SLiane.Praza@Sun.COM 		else
3472*7887SLiane.Praza@Sun.COM 			goto error;
3473*7887SLiane.Praza@Sun.COM 	}
3474*7887SLiane.Praza@Sun.COM 
3475*7887SLiane.Praza@Sun.COM 	if (_read_single_value_from_pg(t->prt_pg,
3476*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CARDINALITY_MAX, &val_max) == 0) {
3477*7887SLiane.Praza@Sun.COM 		if (scf_value_get_count(val_max, max) < 0)
3478*7887SLiane.Praza@Sun.COM 			goto error;
3479*7887SLiane.Praza@Sun.COM 	} else {
3480*7887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND)
3481*7887SLiane.Praza@Sun.COM 			*max = UINT64_MAX;
3482*7887SLiane.Praza@Sun.COM 		else
3483*7887SLiane.Praza@Sun.COM 			goto error;
3484*7887SLiane.Praza@Sun.COM 	}
3485*7887SLiane.Praza@Sun.COM 	goto cleanup;
3486*7887SLiane.Praza@Sun.COM 
3487*7887SLiane.Praza@Sun.COM error:
3488*7887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
3489*7887SLiane.Praza@Sun.COM 		ret = -1;
3490*7887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
3491*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
3492*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
3493*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3494*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
3495*7887SLiane.Praza@Sun.COM 
3496*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_FOUND:
3497*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_TEMPLATE_INVALID:
3498*7887SLiane.Praza@Sun.COM 		ret = -1;
3499*7887SLiane.Praza@Sun.COM 		break;
3500*7887SLiane.Praza@Sun.COM 
3501*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
3502*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
3503*7887SLiane.Praza@Sun.COM 	default:
3504*7887SLiane.Praza@Sun.COM 		assert(0);
3505*7887SLiane.Praza@Sun.COM 		abort();
3506*7887SLiane.Praza@Sun.COM 	}
3507*7887SLiane.Praza@Sun.COM 
3508*7887SLiane.Praza@Sun.COM cleanup:
3509*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val_min);
3510*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val_max);
3511*7887SLiane.Praza@Sun.COM 
3512*7887SLiane.Praza@Sun.COM 	return (ret);
3513*7887SLiane.Praza@Sun.COM }
3514*7887SLiane.Praza@Sun.COM 
3515*7887SLiane.Praza@Sun.COM /*
3516*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3517*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3518*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3519*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3520*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3521*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3522*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3523*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3524*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3525*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3526*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3527*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3528*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3529*7887SLiane.Praza@Sun.COM  */
3530*7887SLiane.Praza@Sun.COM int
3531*7887SLiane.Praza@Sun.COM scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t *t, scf_values_t *vals)
3532*7887SLiane.Praza@Sun.COM {
3533*7887SLiane.Praza@Sun.COM 	if (_read_astrings_values(t->prt_pg,
3534*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_INTERNAL_SEPARATORS, vals) == NULL) {
3535*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3536*7887SLiane.Praza@Sun.COM 			return (-1);
3537*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3538*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3539*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3540*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3541*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
3542*7887SLiane.Praza@Sun.COM 
3543*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3544*7887SLiane.Praza@Sun.COM 			return (-1);
3545*7887SLiane.Praza@Sun.COM 
3546*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3547*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3548*7887SLiane.Praza@Sun.COM 		default:
3549*7887SLiane.Praza@Sun.COM 			assert(0);
3550*7887SLiane.Praza@Sun.COM 			abort();
3551*7887SLiane.Praza@Sun.COM 		}
3552*7887SLiane.Praza@Sun.COM 	} else if (vals->value_count == 0) {
3553*7887SLiane.Praza@Sun.COM 		/* property has no value */
3554*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
3555*7887SLiane.Praza@Sun.COM 		scf_values_destroy(vals);
3556*7887SLiane.Praza@Sun.COM 		return (-1);
3557*7887SLiane.Praza@Sun.COM 	}
3558*7887SLiane.Praza@Sun.COM 
3559*7887SLiane.Praza@Sun.COM 	return (0);
3560*7887SLiane.Praza@Sun.COM }
3561*7887SLiane.Praza@Sun.COM 
3562*7887SLiane.Praza@Sun.COM /*
3563*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3564*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3565*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3566*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3567*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3568*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3569*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3570*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3571*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3572*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3573*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3574*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3575*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3576*7887SLiane.Praza@Sun.COM  */
3577*7887SLiane.Praza@Sun.COM int
3578*7887SLiane.Praza@Sun.COM scf_tmpl_value_name_constraints(const scf_prop_tmpl_t *t,
3579*7887SLiane.Praza@Sun.COM     scf_values_t *vals)
3580*7887SLiane.Praza@Sun.COM {
3581*7887SLiane.Praza@Sun.COM 	char **ret;
3582*7887SLiane.Praza@Sun.COM 
3583*7887SLiane.Praza@Sun.COM 	ret = _read_astrings_values(t->prt_pg,
3584*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CONSTRAINT_NAME, vals);
3585*7887SLiane.Praza@Sun.COM 
3586*7887SLiane.Praza@Sun.COM 	if (ret == NULL) {
3587*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3588*7887SLiane.Praza@Sun.COM 			return (-1);
3589*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3590*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
3591*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3592*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3593*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
3594*7887SLiane.Praza@Sun.COM 
3595*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3596*7887SLiane.Praza@Sun.COM 			return (-1);
3597*7887SLiane.Praza@Sun.COM 
3598*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3599*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3600*7887SLiane.Praza@Sun.COM 		default:
3601*7887SLiane.Praza@Sun.COM 			assert(0);
3602*7887SLiane.Praza@Sun.COM 			abort();
3603*7887SLiane.Praza@Sun.COM 		}
3604*7887SLiane.Praza@Sun.COM 	} else if (vals->value_count == 0) {
3605*7887SLiane.Praza@Sun.COM 		/* property has no value */
3606*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
3607*7887SLiane.Praza@Sun.COM 		scf_values_destroy(vals);
3608*7887SLiane.Praza@Sun.COM 		return (-1);
3609*7887SLiane.Praza@Sun.COM 	}
3610*7887SLiane.Praza@Sun.COM 
3611*7887SLiane.Praza@Sun.COM 	return (0);
3612*7887SLiane.Praza@Sun.COM }
3613*7887SLiane.Praza@Sun.COM 
3614*7887SLiane.Praza@Sun.COM /*
3615*7887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
3616*7887SLiane.Praza@Sun.COM  * Caller is responsible for freeing returned pointer after use.
3617*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
3618*7887SLiane.Praza@Sun.COM  *    More tokens than the array size supplied.
3619*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3620*7887SLiane.Praza@Sun.COM  */
3621*7887SLiane.Praza@Sun.COM static void *
3622*7887SLiane.Praza@Sun.COM _separate_by_separator(char *string, const char *sep, char **array, int size)
3623*7887SLiane.Praza@Sun.COM {
3624*7887SLiane.Praza@Sun.COM 	char *str, *token;
3625*7887SLiane.Praza@Sun.COM 	char *lasts;
3626*7887SLiane.Praza@Sun.COM 	int n = 0;
3627*7887SLiane.Praza@Sun.COM 
3628*7887SLiane.Praza@Sun.COM 	assert(array != NULL);
3629*7887SLiane.Praza@Sun.COM 	assert(string != NULL);
3630*7887SLiane.Praza@Sun.COM 	assert(sep != NULL);
3631*7887SLiane.Praza@Sun.COM 	assert(size > 0);
3632*7887SLiane.Praza@Sun.COM 
3633*7887SLiane.Praza@Sun.COM 	str = strdup(string);
3634*7887SLiane.Praza@Sun.COM 	if (str == NULL) {
3635*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
3636*7887SLiane.Praza@Sun.COM 		return (NULL);
3637*7887SLiane.Praza@Sun.COM 	}
3638*7887SLiane.Praza@Sun.COM 
3639*7887SLiane.Praza@Sun.COM 	if ((array[n] = strtok_r(str, sep, &lasts)) == NULL) {
3640*7887SLiane.Praza@Sun.COM 		assert(0);
3641*7887SLiane.Praza@Sun.COM 		abort();
3642*7887SLiane.Praza@Sun.COM 	}
3643*7887SLiane.Praza@Sun.COM 
3644*7887SLiane.Praza@Sun.COM 	n++;
3645*7887SLiane.Praza@Sun.COM 	while ((token = strtok_r(NULL, sep, &lasts)) != NULL) {
3646*7887SLiane.Praza@Sun.COM 		if (n >= size) {
3647*7887SLiane.Praza@Sun.COM 			goto error;
3648*7887SLiane.Praza@Sun.COM 		}
3649*7887SLiane.Praza@Sun.COM 		array[n] = token;
3650*7887SLiane.Praza@Sun.COM 		n++;
3651*7887SLiane.Praza@Sun.COM 	}
3652*7887SLiane.Praza@Sun.COM 	if (n < size) {
3653*7887SLiane.Praza@Sun.COM 		goto error;
3654*7887SLiane.Praza@Sun.COM 	}
3655*7887SLiane.Praza@Sun.COM 
3656*7887SLiane.Praza@Sun.COM 	return (str);
3657*7887SLiane.Praza@Sun.COM error:
3658*7887SLiane.Praza@Sun.COM 	free(str);
3659*7887SLiane.Praza@Sun.COM 	(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
3660*7887SLiane.Praza@Sun.COM 	return (NULL);
3661*7887SLiane.Praza@Sun.COM }
3662*7887SLiane.Praza@Sun.COM 
3663*7887SLiane.Praza@Sun.COM /*
3664*7887SLiane.Praza@Sun.COM  * check if name is among values of CHOICES_INCLUDE_VALUES
3665*7887SLiane.Praza@Sun.COM  * return 0 if name is present, 1 name is not present, -1 on failure
3666*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3667*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3668*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3669*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3670*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3671*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3672*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3673*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3674*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3675*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3676*7887SLiane.Praza@Sun.COM  */
3677*7887SLiane.Praza@Sun.COM static int
3678*7887SLiane.Praza@Sun.COM _check_choices_include_values(scf_propertygroup_t *pg, const char *name)
3679*7887SLiane.Praza@Sun.COM {
3680*7887SLiane.Praza@Sun.COM 	int n = 0, r = 1;
3681*7887SLiane.Praza@Sun.COM 	char **ret;
3682*7887SLiane.Praza@Sun.COM 	scf_values_t vals;
3683*7887SLiane.Praza@Sun.COM 
3684*7887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(pg,
3685*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES, &vals)) == NULL) {
3686*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
3687*7887SLiane.Praza@Sun.COM 			return (-1);
3688*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
3689*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
3690*7887SLiane.Praza@Sun.COM 			return (1);
3691*7887SLiane.Praza@Sun.COM 
3692*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
3693*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3694*7887SLiane.Praza@Sun.COM 			return (-1);
3695*7887SLiane.Praza@Sun.COM 
3696*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
3697*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
3698*7887SLiane.Praza@Sun.COM 		default:
3699*7887SLiane.Praza@Sun.COM 			assert(0);
3700*7887SLiane.Praza@Sun.COM 			abort();
3701*7887SLiane.Praza@Sun.COM 		}
3702*7887SLiane.Praza@Sun.COM 	}
3703*7887SLiane.Praza@Sun.COM 
3704*7887SLiane.Praza@Sun.COM 	for (n = 0; n < vals.value_count; ++n) {
3705*7887SLiane.Praza@Sun.COM 		if (strcmp(name, ret[n]) == 0) {
3706*7887SLiane.Praza@Sun.COM 			r = 0;
3707*7887SLiane.Praza@Sun.COM 			break;
3708*7887SLiane.Praza@Sun.COM 		}
3709*7887SLiane.Praza@Sun.COM 	}
3710*7887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
3711*7887SLiane.Praza@Sun.COM 	return (r);
3712*7887SLiane.Praza@Sun.COM }
3713*7887SLiane.Praza@Sun.COM 
3714*7887SLiane.Praza@Sun.COM void
3715*7887SLiane.Praza@Sun.COM scf_count_ranges_destroy(scf_count_ranges_t *ranges)
3716*7887SLiane.Praza@Sun.COM {
3717*7887SLiane.Praza@Sun.COM 	if (ranges == NULL)
3718*7887SLiane.Praza@Sun.COM 		return;
3719*7887SLiane.Praza@Sun.COM 
3720*7887SLiane.Praza@Sun.COM 	ranges->scr_num_ranges = 0;
3721*7887SLiane.Praza@Sun.COM 	free(ranges->scr_min);
3722*7887SLiane.Praza@Sun.COM 	free(ranges->scr_max);
3723*7887SLiane.Praza@Sun.COM 	ranges->scr_min = NULL;
3724*7887SLiane.Praza@Sun.COM 	ranges->scr_max = NULL;
3725*7887SLiane.Praza@Sun.COM }
3726*7887SLiane.Praza@Sun.COM 
3727*7887SLiane.Praza@Sun.COM void
3728*7887SLiane.Praza@Sun.COM scf_int_ranges_destroy(scf_int_ranges_t *ranges)
3729*7887SLiane.Praza@Sun.COM {
3730*7887SLiane.Praza@Sun.COM 	if (ranges == NULL)
3731*7887SLiane.Praza@Sun.COM 		return;
3732*7887SLiane.Praza@Sun.COM 
3733*7887SLiane.Praza@Sun.COM 	ranges->sir_num_ranges = 0;
3734*7887SLiane.Praza@Sun.COM 	free(ranges->sir_min);
3735*7887SLiane.Praza@Sun.COM 	free(ranges->sir_max);
3736*7887SLiane.Praza@Sun.COM 	ranges->sir_min = NULL;
3737*7887SLiane.Praza@Sun.COM 	ranges->sir_max = NULL;
3738*7887SLiane.Praza@Sun.COM }
3739*7887SLiane.Praza@Sun.COM 
3740*7887SLiane.Praza@Sun.COM /*
3741*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3742*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3743*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3744*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
3745*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3746*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3747*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3748*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3749*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3750*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3751*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3752*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3753*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3754*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3755*7887SLiane.Praza@Sun.COM  */
3756*7887SLiane.Praza@Sun.COM static int
3757*7887SLiane.Praza@Sun.COM _scf_tmpl_get_count_ranges(const scf_prop_tmpl_t *t, const char *prop,
3758*7887SLiane.Praza@Sun.COM     scf_count_ranges_t *ranges)
3759*7887SLiane.Praza@Sun.COM {
3760*7887SLiane.Praza@Sun.COM 	scf_values_t vals;
3761*7887SLiane.Praza@Sun.COM 	int i = 0;
3762*7887SLiane.Praza@Sun.COM 	char **ret;
3763*7887SLiane.Praza@Sun.COM 	char *one_range[2];
3764*7887SLiane.Praza@Sun.COM 	char *endptr;
3765*7887SLiane.Praza@Sun.COM 	char *str = NULL;
3766*7887SLiane.Praza@Sun.COM 	uint64_t *min = NULL;
3767*7887SLiane.Praza@Sun.COM 	uint64_t *max = NULL;
3768*7887SLiane.Praza@Sun.COM 
3769*7887SLiane.Praza@Sun.COM 	assert(ranges != NULL);
3770*7887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL)
3771*7887SLiane.Praza@Sun.COM 		goto error;
3772*7887SLiane.Praza@Sun.COM 	if (vals.value_count == 0) {
3773*7887SLiane.Praza@Sun.COM 		/* range values are empty */
3774*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
3775*7887SLiane.Praza@Sun.COM 		goto cleanup;
3776*7887SLiane.Praza@Sun.COM 	}
3777*7887SLiane.Praza@Sun.COM 
3778*7887SLiane.Praza@Sun.COM 	min = malloc(vals.value_count * sizeof (uint64_t));
3779*7887SLiane.Praza@Sun.COM 	max = malloc(vals.value_count * sizeof (uint64_t));
3780*7887SLiane.Praza@Sun.COM 	if (min == NULL || max == NULL) {
3781*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
3782*7887SLiane.Praza@Sun.COM 		goto cleanup;
3783*7887SLiane.Praza@Sun.COM 	}
3784*7887SLiane.Praza@Sun.COM 	for (i = 0; i < vals.value_count; ++i) {
3785*7887SLiane.Praza@Sun.COM 		/* min and max should be separated by a "," */
3786*7887SLiane.Praza@Sun.COM 		if ((str = _separate_by_separator(ret[i], ",", one_range,
3787*7887SLiane.Praza@Sun.COM 		    2)) == NULL)
3788*7887SLiane.Praza@Sun.COM 			goto cleanup;
3789*7887SLiane.Praza@Sun.COM 		errno = 0;
3790*7887SLiane.Praza@Sun.COM 		min[i] = strtoull(one_range[0], &endptr, 10);
3791*7887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[0] || *endptr) {
3792*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
3793*7887SLiane.Praza@Sun.COM 			goto cleanup;
3794*7887SLiane.Praza@Sun.COM 		}
3795*7887SLiane.Praza@Sun.COM 		errno = 0;
3796*7887SLiane.Praza@Sun.COM 		max[i] = strtoull(one_range[1], &endptr, 10);
3797*7887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[1] || *endptr) {
3798*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
3799*7887SLiane.Praza@Sun.COM 			goto cleanup;
3800*7887SLiane.Praza@Sun.COM 		}
3801*7887SLiane.Praza@Sun.COM 		if (min[i] > max[i]) {
3802*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
3803*7887SLiane.Praza@Sun.COM 			goto cleanup;
3804*7887SLiane.Praza@Sun.COM 		}
3805*7887SLiane.Praza@Sun.COM 		free(str);
3806*7887SLiane.Praza@Sun.COM 		str = NULL;
3807*7887SLiane.Praza@Sun.COM 	}
3808*7887SLiane.Praza@Sun.COM 	ranges->scr_num_ranges = vals.value_count;
3809*7887SLiane.Praza@Sun.COM 	ranges->scr_min = min;
3810*7887SLiane.Praza@Sun.COM 	ranges->scr_max = max;
3811*7887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
3812*7887SLiane.Praza@Sun.COM 	return (0);
3813*7887SLiane.Praza@Sun.COM cleanup:
3814*7887SLiane.Praza@Sun.COM 	free(str);
3815*7887SLiane.Praza@Sun.COM 	free(min);
3816*7887SLiane.Praza@Sun.COM 	free(max);
3817*7887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
3818*7887SLiane.Praza@Sun.COM error:
3819*7887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
3820*7887SLiane.Praza@Sun.COM 		return (-1);
3821*7887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
3822*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
3823*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3824*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
3825*7887SLiane.Praza@Sun.COM 
3826*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
3827*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_FOUND:
3828*7887SLiane.Praza@Sun.COM 		return (-1);
3829*7887SLiane.Praza@Sun.COM 
3830*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
3831*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
3832*7887SLiane.Praza@Sun.COM 	default:
3833*7887SLiane.Praza@Sun.COM 		assert(0);
3834*7887SLiane.Praza@Sun.COM 		abort();
3835*7887SLiane.Praza@Sun.COM 	}
3836*7887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
3837*7887SLiane.Praza@Sun.COM }
3838*7887SLiane.Praza@Sun.COM 
3839*7887SLiane.Praza@Sun.COM /*
3840*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3841*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3842*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3843*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
3844*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3845*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3846*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3847*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3848*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3849*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3850*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3851*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3852*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3853*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3854*7887SLiane.Praza@Sun.COM  */
3855*7887SLiane.Praza@Sun.COM static int
3856*7887SLiane.Praza@Sun.COM _scf_tmpl_get_int_ranges(const scf_prop_tmpl_t *t, const char *prop,
3857*7887SLiane.Praza@Sun.COM     scf_int_ranges_t *ranges)
3858*7887SLiane.Praza@Sun.COM {
3859*7887SLiane.Praza@Sun.COM 	scf_values_t vals;
3860*7887SLiane.Praza@Sun.COM 	int n = 0;
3861*7887SLiane.Praza@Sun.COM 	char **ret;
3862*7887SLiane.Praza@Sun.COM 	char *one_range[2];
3863*7887SLiane.Praza@Sun.COM 	char *endptr;
3864*7887SLiane.Praza@Sun.COM 	char *str = NULL;
3865*7887SLiane.Praza@Sun.COM 	int64_t *min = NULL;
3866*7887SLiane.Praza@Sun.COM 	int64_t *max = NULL;
3867*7887SLiane.Praza@Sun.COM 
3868*7887SLiane.Praza@Sun.COM 	assert(ranges != NULL);
3869*7887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL)
3870*7887SLiane.Praza@Sun.COM 		goto error;
3871*7887SLiane.Praza@Sun.COM 	if (vals.value_count == 0) {
3872*7887SLiane.Praza@Sun.COM 		/* range values are empty */
3873*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
3874*7887SLiane.Praza@Sun.COM 		goto cleanup;
3875*7887SLiane.Praza@Sun.COM 	}
3876*7887SLiane.Praza@Sun.COM 
3877*7887SLiane.Praza@Sun.COM 	min = malloc(vals.value_count * sizeof (int64_t));
3878*7887SLiane.Praza@Sun.COM 	max = malloc(vals.value_count * sizeof (int64_t));
3879*7887SLiane.Praza@Sun.COM 	if (min == NULL || max == NULL) {
3880*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
3881*7887SLiane.Praza@Sun.COM 		goto cleanup;
3882*7887SLiane.Praza@Sun.COM 	}
3883*7887SLiane.Praza@Sun.COM 	while (n < vals.value_count) {
3884*7887SLiane.Praza@Sun.COM 		/* min and max should be separated by a "," */
3885*7887SLiane.Praza@Sun.COM 		if ((str = _separate_by_separator(ret[n], ",", one_range, 2))
3886*7887SLiane.Praza@Sun.COM 		    == NULL)
3887*7887SLiane.Praza@Sun.COM 			goto cleanup;
3888*7887SLiane.Praza@Sun.COM 		errno = 0;
3889*7887SLiane.Praza@Sun.COM 		min[n] = strtoll(one_range[0], &endptr, 10);
3890*7887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[0] || *endptr) {
3891*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
3892*7887SLiane.Praza@Sun.COM 			goto cleanup;
3893*7887SLiane.Praza@Sun.COM 		}
3894*7887SLiane.Praza@Sun.COM 		errno = 0;
3895*7887SLiane.Praza@Sun.COM 		max[n] = strtoll(one_range[1], &endptr, 10);
3896*7887SLiane.Praza@Sun.COM 		if (errno != 0 || endptr == one_range[1] || *endptr) {
3897*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
3898*7887SLiane.Praza@Sun.COM 			goto cleanup;
3899*7887SLiane.Praza@Sun.COM 		}
3900*7887SLiane.Praza@Sun.COM 		if (min[n] > max[n]) {
3901*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3902*7887SLiane.Praza@Sun.COM 			goto cleanup;
3903*7887SLiane.Praza@Sun.COM 		}
3904*7887SLiane.Praza@Sun.COM 		++n;
3905*7887SLiane.Praza@Sun.COM 		free(str);
3906*7887SLiane.Praza@Sun.COM 		str = NULL;
3907*7887SLiane.Praza@Sun.COM 	}
3908*7887SLiane.Praza@Sun.COM 	ranges->sir_num_ranges = vals.value_count;
3909*7887SLiane.Praza@Sun.COM 	ranges->sir_min = min;
3910*7887SLiane.Praza@Sun.COM 	ranges->sir_max = max;
3911*7887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
3912*7887SLiane.Praza@Sun.COM 	return (0);
3913*7887SLiane.Praza@Sun.COM cleanup:
3914*7887SLiane.Praza@Sun.COM 	free(str);
3915*7887SLiane.Praza@Sun.COM 	free(min);
3916*7887SLiane.Praza@Sun.COM 	free(max);
3917*7887SLiane.Praza@Sun.COM 	scf_values_destroy(&vals);
3918*7887SLiane.Praza@Sun.COM error:
3919*7887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
3920*7887SLiane.Praza@Sun.COM 		return (-1);
3921*7887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
3922*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
3923*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
3924*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
3925*7887SLiane.Praza@Sun.COM 
3926*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
3927*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_FOUND:
3928*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_TEMPLATE_INVALID:
3929*7887SLiane.Praza@Sun.COM 		return (-1);
3930*7887SLiane.Praza@Sun.COM 
3931*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
3932*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
3933*7887SLiane.Praza@Sun.COM 	default:
3934*7887SLiane.Praza@Sun.COM 		assert(0);
3935*7887SLiane.Praza@Sun.COM 		abort();
3936*7887SLiane.Praza@Sun.COM 	}
3937*7887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
3938*7887SLiane.Praza@Sun.COM }
3939*7887SLiane.Praza@Sun.COM 
3940*7887SLiane.Praza@Sun.COM /*
3941*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3942*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3943*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3944*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONSTRAINT_VIOLATED
3945*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3946*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3947*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3948*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3949*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3950*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3951*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3952*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
3953*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
3954*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
3955*7887SLiane.Praza@Sun.COM  */
3956*7887SLiane.Praza@Sun.COM int
3957*7887SLiane.Praza@Sun.COM scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t *t,
3958*7887SLiane.Praza@Sun.COM     scf_count_ranges_t *ranges)
3959*7887SLiane.Praza@Sun.COM {
3960*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE,
3961*7887SLiane.Praza@Sun.COM 	    ranges));
3962*7887SLiane.Praza@Sun.COM }
3963*7887SLiane.Praza@Sun.COM 
3964*7887SLiane.Praza@Sun.COM int
3965*7887SLiane.Praza@Sun.COM scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t *t,
3966*7887SLiane.Praza@Sun.COM     scf_int_ranges_t *ranges)
3967*7887SLiane.Praza@Sun.COM {
3968*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE,
3969*7887SLiane.Praza@Sun.COM 	    ranges));
3970*7887SLiane.Praza@Sun.COM }
3971*7887SLiane.Praza@Sun.COM 
3972*7887SLiane.Praza@Sun.COM int
3973*7887SLiane.Praza@Sun.COM scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t *t,
3974*7887SLiane.Praza@Sun.COM     scf_count_ranges_t *ranges)
3975*7887SLiane.Praza@Sun.COM {
3976*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE,
3977*7887SLiane.Praza@Sun.COM 	    ranges));
3978*7887SLiane.Praza@Sun.COM }
3979*7887SLiane.Praza@Sun.COM 
3980*7887SLiane.Praza@Sun.COM int
3981*7887SLiane.Praza@Sun.COM scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t *t,
3982*7887SLiane.Praza@Sun.COM     scf_int_ranges_t *ranges)
3983*7887SLiane.Praza@Sun.COM {
3984*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE,
3985*7887SLiane.Praza@Sun.COM 	    ranges));
3986*7887SLiane.Praza@Sun.COM }
3987*7887SLiane.Praza@Sun.COM 
3988*7887SLiane.Praza@Sun.COM /*
3989*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
3990*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
3991*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
3992*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
3993*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
3994*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
3995*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
3996*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
3997*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
3998*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
3999*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
4000*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
4001*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
4002*7887SLiane.Praza@Sun.COM  */
4003*7887SLiane.Praza@Sun.COM int
4004*7887SLiane.Praza@Sun.COM scf_tmpl_value_name_choices(const scf_prop_tmpl_t *t, scf_values_t *vals)
4005*7887SLiane.Praza@Sun.COM {
4006*7887SLiane.Praza@Sun.COM 	int c_flag = 0; /* have not read any value yet */
4007*7887SLiane.Praza@Sun.COM 	int r;
4008*7887SLiane.Praza@Sun.COM 	char **ret;
4009*7887SLiane.Praza@Sun.COM 
4010*7887SLiane.Praza@Sun.COM 	/* First, look for explicitly declared choices. */
4011*7887SLiane.Praza@Sun.COM 	if ((ret = _read_astrings_values(t->prt_pg,
4012*7887SLiane.Praza@Sun.COM 	    SCF_PROPERTY_TM_CHOICES_NAME, vals)) != NULL) {
4013*7887SLiane.Praza@Sun.COM 		c_flag = 1;
4014*7887SLiane.Praza@Sun.COM 	} else if (scf_error() != SCF_ERROR_NOT_FOUND) {
4015*7887SLiane.Praza@Sun.COM 		goto error;
4016*7887SLiane.Praza@Sun.COM 	}
4017*7887SLiane.Praza@Sun.COM 
4018*7887SLiane.Praza@Sun.COM 	/* Next, check for choices included by 'values'. */
4019*7887SLiane.Praza@Sun.COM 	if ((r = _check_choices_include_values(t->prt_pg, "values")) == 0) {
4020*7887SLiane.Praza@Sun.COM 		/* read values_name */
4021*7887SLiane.Praza@Sun.COM 		if (c_flag == 1)
4022*7887SLiane.Praza@Sun.COM 			/* append values */
4023*7887SLiane.Praza@Sun.COM 			ret = _append_astrings_values(t->prt_pg,
4024*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_VALUES_NAME, vals);
4025*7887SLiane.Praza@Sun.COM 		else
4026*7887SLiane.Praza@Sun.COM 			/* read values */
4027*7887SLiane.Praza@Sun.COM 			ret = _read_astrings_values(t->prt_pg,
4028*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_VALUES_NAME, vals);
4029*7887SLiane.Praza@Sun.COM 		if (ret != NULL) {
4030*7887SLiane.Praza@Sun.COM 			c_flag = 1;
4031*7887SLiane.Praza@Sun.COM 		} else if (scf_error() != SCF_ERROR_NOT_FOUND) {
4032*7887SLiane.Praza@Sun.COM 			goto error;
4033*7887SLiane.Praza@Sun.COM 		}
4034*7887SLiane.Praza@Sun.COM 	} else if (r == -1) {
4035*7887SLiane.Praza@Sun.COM 		goto error;
4036*7887SLiane.Praza@Sun.COM 	}
4037*7887SLiane.Praza@Sun.COM 
4038*7887SLiane.Praza@Sun.COM 	/* Finally check for choices included by 'constraints'. */
4039*7887SLiane.Praza@Sun.COM 	if ((r = _check_choices_include_values(t->prt_pg, "constraints")) ==
4040*7887SLiane.Praza@Sun.COM 	    0) {
4041*7887SLiane.Praza@Sun.COM 		/* read constraint_name */
4042*7887SLiane.Praza@Sun.COM 		if (c_flag == 1)
4043*7887SLiane.Praza@Sun.COM 			/* append values */
4044*7887SLiane.Praza@Sun.COM 			ret = _append_astrings_values(t->prt_pg,
4045*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_CONSTRAINT_NAME, vals);
4046*7887SLiane.Praza@Sun.COM 		else
4047*7887SLiane.Praza@Sun.COM 			/* read values */
4048*7887SLiane.Praza@Sun.COM 			ret = _read_astrings_values(t->prt_pg,
4049*7887SLiane.Praza@Sun.COM 			    SCF_PROPERTY_TM_CONSTRAINT_NAME, vals);
4050*7887SLiane.Praza@Sun.COM 		if (ret != NULL) {
4051*7887SLiane.Praza@Sun.COM 			c_flag = 1;
4052*7887SLiane.Praza@Sun.COM 		} else if (scf_error() != SCF_ERROR_NOT_FOUND) {
4053*7887SLiane.Praza@Sun.COM 			goto error;
4054*7887SLiane.Praza@Sun.COM 		}
4055*7887SLiane.Praza@Sun.COM 	} else if (r == -1) {
4056*7887SLiane.Praza@Sun.COM 		goto error;
4057*7887SLiane.Praza@Sun.COM 	}
4058*7887SLiane.Praza@Sun.COM 
4059*7887SLiane.Praza@Sun.COM 	if (c_flag == 0 || vals->value_count == 0) {
4060*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
4061*7887SLiane.Praza@Sun.COM 		return (-1);
4062*7887SLiane.Praza@Sun.COM 	}
4063*7887SLiane.Praza@Sun.COM 
4064*7887SLiane.Praza@Sun.COM 	return (0);
4065*7887SLiane.Praza@Sun.COM 
4066*7887SLiane.Praza@Sun.COM error:
4067*7887SLiane.Praza@Sun.COM 	if (ismember(scf_error(), errors_server)) {
4068*7887SLiane.Praza@Sun.COM 		return (-1);
4069*7887SLiane.Praza@Sun.COM 	} else switch (scf_error()) {
4070*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
4071*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
4072*7887SLiane.Praza@Sun.COM 		return (-1);
4073*7887SLiane.Praza@Sun.COM 
4074*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_NOT_SET:
4075*7887SLiane.Praza@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
4076*7887SLiane.Praza@Sun.COM 	default:
4077*7887SLiane.Praza@Sun.COM 		assert(0);
4078*7887SLiane.Praza@Sun.COM 		abort();
4079*7887SLiane.Praza@Sun.COM 	}
4080*7887SLiane.Praza@Sun.COM 	/*NOTREACHED*/
4081*7887SLiane.Praza@Sun.COM }
4082*7887SLiane.Praza@Sun.COM 
4083*7887SLiane.Praza@Sun.COM void
4084*7887SLiane.Praza@Sun.COM scf_values_destroy(scf_values_t *vals)
4085*7887SLiane.Praza@Sun.COM {
4086*7887SLiane.Praza@Sun.COM 	int i;
4087*7887SLiane.Praza@Sun.COM 	char **items = NULL;
4088*7887SLiane.Praza@Sun.COM 	char **str = vals->values_as_strings;
4089*7887SLiane.Praza@Sun.COM 
4090*7887SLiane.Praza@Sun.COM 	if (vals == NULL)
4091*7887SLiane.Praza@Sun.COM 		return;
4092*7887SLiane.Praza@Sun.COM 
4093*7887SLiane.Praza@Sun.COM 	/* free values */
4094*7887SLiane.Praza@Sun.COM 	switch (vals->value_type) {
4095*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_BOOLEAN:
4096*7887SLiane.Praza@Sun.COM 		free(vals->values.v_boolean);
4097*7887SLiane.Praza@Sun.COM 		break;
4098*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_COUNT:
4099*7887SLiane.Praza@Sun.COM 		free(vals->values.v_count);
4100*7887SLiane.Praza@Sun.COM 		break;
4101*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_INTEGER:
4102*7887SLiane.Praza@Sun.COM 		free(vals->values.v_integer);
4103*7887SLiane.Praza@Sun.COM 		break;
4104*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_ASTRING:
4105*7887SLiane.Praza@Sun.COM 		items = vals->values.v_astring;
4106*7887SLiane.Praza@Sun.COM 		str = NULL;
4107*7887SLiane.Praza@Sun.COM 		break;
4108*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_USTRING:
4109*7887SLiane.Praza@Sun.COM 		items = vals->values.v_ustring;
4110*7887SLiane.Praza@Sun.COM 		str = NULL;
4111*7887SLiane.Praza@Sun.COM 		break;
4112*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_OPAQUE:
4113*7887SLiane.Praza@Sun.COM 		items = vals->values.v_opaque;
4114*7887SLiane.Praza@Sun.COM 		str = NULL;
4115*7887SLiane.Praza@Sun.COM 		break;
4116*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_TIME:
4117*7887SLiane.Praza@Sun.COM 		free(vals->values.v_time);
4118*7887SLiane.Praza@Sun.COM 		break;
4119*7887SLiane.Praza@Sun.COM 	default:
4120*7887SLiane.Praza@Sun.COM 		assert(0);
4121*7887SLiane.Praza@Sun.COM 		abort();
4122*7887SLiane.Praza@Sun.COM 	}
4123*7887SLiane.Praza@Sun.COM 	for (i = 0; i < vals->value_count; ++i) {
4124*7887SLiane.Praza@Sun.COM 		if (items != NULL)
4125*7887SLiane.Praza@Sun.COM 			free(items[i]);
4126*7887SLiane.Praza@Sun.COM 		if (str != NULL)
4127*7887SLiane.Praza@Sun.COM 			free(str[i]);
4128*7887SLiane.Praza@Sun.COM 	}
4129*7887SLiane.Praza@Sun.COM 	vals->value_count = 0;
4130*7887SLiane.Praza@Sun.COM 	free(items);
4131*7887SLiane.Praza@Sun.COM 	free(str);
4132*7887SLiane.Praza@Sun.COM }
4133*7887SLiane.Praza@Sun.COM 
4134*7887SLiane.Praza@Sun.COM /*
4135*7887SLiane.Praza@Sun.COM  * char *_make_value_name()
4136*7887SLiane.Praza@Sun.COM  *
4137*7887SLiane.Praza@Sun.COM  * Construct the prefix for a value common name or value description property.
4138*7887SLiane.Praza@Sun.COM  * It takes the form:
4139*7887SLiane.Praza@Sun.COM  *   value_<BASE32 name>_<common_name|description>_
4140*7887SLiane.Praza@Sun.COM  * This is then combined with a localized suffix by the caller to look
4141*7887SLiane.Praza@Sun.COM  * up the property in the repository:
4142*7887SLiane.Praza@Sun.COM  *   value_<BASE32 name>_<common_name|description>_<lang>
4143*7887SLiane.Praza@Sun.COM  *
4144*7887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
4145*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
4146*7887SLiane.Praza@Sun.COM  *     Name isn't short enough make a value name with.
4147*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4148*7887SLiane.Praza@Sun.COM  */
4149*7887SLiane.Praza@Sun.COM static char *
4150*7887SLiane.Praza@Sun.COM _make_value_name(char *desc_name, const char *value)
4151*7887SLiane.Praza@Sun.COM {
4152*7887SLiane.Praza@Sun.COM 	char *name = NULL;
4153*7887SLiane.Praza@Sun.COM 	char *encoded = NULL;
4154*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
4155*7887SLiane.Praza@Sun.COM 
4156*7887SLiane.Praza@Sun.COM 	name = malloc(sz);
4157*7887SLiane.Praza@Sun.COM 	encoded = malloc(sz);
4158*7887SLiane.Praza@Sun.COM 	if (name == NULL || encoded == NULL) {
4159*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4160*7887SLiane.Praza@Sun.COM 		free(name);
4161*7887SLiane.Praza@Sun.COM 		free(encoded);
4162*7887SLiane.Praza@Sun.COM 		return (NULL);
4163*7887SLiane.Praza@Sun.COM 	}
4164*7887SLiane.Praza@Sun.COM 
4165*7887SLiane.Praza@Sun.COM 	if (scf_encode32(value, strlen(value), encoded, sz, NULL,
4166*7887SLiane.Praza@Sun.COM 	    SCF_ENCODE32_PAD) != 0) {
4167*7887SLiane.Praza@Sun.COM 		/* Shouldn't happen. */
4168*7887SLiane.Praza@Sun.COM 		assert(0);
4169*7887SLiane.Praza@Sun.COM 	}
4170*7887SLiane.Praza@Sun.COM 
4171*7887SLiane.Praza@Sun.COM 	(void) strlcpy(name, SCF_PROPERTY_TM_VALUE_PREFIX, sz);
4172*7887SLiane.Praza@Sun.COM 
4173*7887SLiane.Praza@Sun.COM 	if (strlcat(name, encoded, sz) >= sz) {
4174*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
4175*7887SLiane.Praza@Sun.COM 		free(name);
4176*7887SLiane.Praza@Sun.COM 		free(encoded);
4177*7887SLiane.Praza@Sun.COM 		return (NULL);
4178*7887SLiane.Praza@Sun.COM 	}
4179*7887SLiane.Praza@Sun.COM 
4180*7887SLiane.Praza@Sun.COM 	if (strlcat(name, "_", sz) >= sz) {
4181*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
4182*7887SLiane.Praza@Sun.COM 		free(name);
4183*7887SLiane.Praza@Sun.COM 		free(encoded);
4184*7887SLiane.Praza@Sun.COM 		return (NULL);
4185*7887SLiane.Praza@Sun.COM 	}
4186*7887SLiane.Praza@Sun.COM 
4187*7887SLiane.Praza@Sun.COM 	if (strlcat(name, desc_name, sz) >= sz) {
4188*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
4189*7887SLiane.Praza@Sun.COM 		free(name);
4190*7887SLiane.Praza@Sun.COM 		free(encoded);
4191*7887SLiane.Praza@Sun.COM 		return (NULL);
4192*7887SLiane.Praza@Sun.COM 	}
4193*7887SLiane.Praza@Sun.COM 
4194*7887SLiane.Praza@Sun.COM 	if (strlcat(name, "_", sz) >= sz) {
4195*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
4196*7887SLiane.Praza@Sun.COM 		free(name);
4197*7887SLiane.Praza@Sun.COM 		free(encoded);
4198*7887SLiane.Praza@Sun.COM 		return (NULL);
4199*7887SLiane.Praza@Sun.COM 	}
4200*7887SLiane.Praza@Sun.COM 
4201*7887SLiane.Praza@Sun.COM 	free(encoded);
4202*7887SLiane.Praza@Sun.COM 	return (name);
4203*7887SLiane.Praza@Sun.COM }
4204*7887SLiane.Praza@Sun.COM 
4205*7887SLiane.Praza@Sun.COM /*
4206*7887SLiane.Praza@Sun.COM  * ssize_t scf_tmpl_value_common_name()
4207*7887SLiane.Praza@Sun.COM  *
4208*7887SLiane.Praza@Sun.COM  * Populates "out" with an allocated string containing the value's
4209*7887SLiane.Praza@Sun.COM  * common name.  Returns the size of the string on successful return.
4210*7887SLiane.Praza@Sun.COM  * out must be freed with free() on successful return.
4211*7887SLiane.Praza@Sun.COM  *
4212*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
4213*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
4214*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
4215*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
4216*7887SLiane.Praza@Sun.COM  *     Property group was deleted.
4217*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
4218*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
4219*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
4220*7887SLiane.Praza@Sun.COM  *     name not a valid property name
4221*7887SLiane.Praza@Sun.COM  *     name and locale are too long to make a property name
4222*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4223*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
4224*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
4225*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
4226*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
4227*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
4228*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
4229*7887SLiane.Praza@Sun.COM  *     property is not SCF_TYPE_ASTRING has more than one value.
4230*7887SLiane.Praza@Sun.COM  */
4231*7887SLiane.Praza@Sun.COM ssize_t
4232*7887SLiane.Praza@Sun.COM scf_tmpl_value_common_name(const scf_prop_tmpl_t *t, const char *locale,
4233*7887SLiane.Praza@Sun.COM     const char *value, char **out)
4234*7887SLiane.Praza@Sun.COM {
4235*7887SLiane.Praza@Sun.COM 	char *value_name = NULL;
4236*7887SLiane.Praza@Sun.COM 
4237*7887SLiane.Praza@Sun.COM 	value_name = _make_value_name("common_name", value);
4238*7887SLiane.Praza@Sun.COM 	if (value_name == NULL)
4239*7887SLiane.Praza@Sun.COM 		return (-1);
4240*7887SLiane.Praza@Sun.COM 
4241*7887SLiane.Praza@Sun.COM 	*out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale);
4242*7887SLiane.Praza@Sun.COM 
4243*7887SLiane.Praza@Sun.COM 	free(value_name);
4244*7887SLiane.Praza@Sun.COM 
4245*7887SLiane.Praza@Sun.COM 	if (*out == NULL)
4246*7887SLiane.Praza@Sun.COM 		return (-1);
4247*7887SLiane.Praza@Sun.COM 
4248*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
4249*7887SLiane.Praza@Sun.COM }
4250*7887SLiane.Praza@Sun.COM 
4251*7887SLiane.Praza@Sun.COM /*
4252*7887SLiane.Praza@Sun.COM  * ssize_t scf_tmpl_value_description()
4253*7887SLiane.Praza@Sun.COM  *
4254*7887SLiane.Praza@Sun.COM  * Populates "out" with an allocated string containing the value's
4255*7887SLiane.Praza@Sun.COM  * description.  Returns the size of the string on successful return.
4256*7887SLiane.Praza@Sun.COM  * out must be freed with free() on successful return.
4257*7887SLiane.Praza@Sun.COM  *
4258*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
4259*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
4260*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
4261*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
4262*7887SLiane.Praza@Sun.COM  *     Property group was deleted.
4263*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
4264*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
4265*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
4266*7887SLiane.Praza@Sun.COM  *     name not a valid property name
4267*7887SLiane.Praza@Sun.COM  *     name and locale are too long to make a property name
4268*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4269*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
4270*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
4271*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
4272*7887SLiane.Praza@Sun.COM  *     Property doesn't exist or exists and has no value.
4273*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
4274*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
4275*7887SLiane.Praza@Sun.COM  *     property is not SCF_TYPE_ASTRING has more than one value.
4276*7887SLiane.Praza@Sun.COM  */
4277*7887SLiane.Praza@Sun.COM ssize_t
4278*7887SLiane.Praza@Sun.COM scf_tmpl_value_description(const scf_prop_tmpl_t *t, const char *locale,
4279*7887SLiane.Praza@Sun.COM     const char *value, char **out)
4280*7887SLiane.Praza@Sun.COM {
4281*7887SLiane.Praza@Sun.COM 	char *value_name = NULL;
4282*7887SLiane.Praza@Sun.COM 
4283*7887SLiane.Praza@Sun.COM 	value_name = _make_value_name("description", value);
4284*7887SLiane.Praza@Sun.COM 	if (value_name == NULL)
4285*7887SLiane.Praza@Sun.COM 		return (-1);
4286*7887SLiane.Praza@Sun.COM 
4287*7887SLiane.Praza@Sun.COM 
4288*7887SLiane.Praza@Sun.COM 	*out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale);
4289*7887SLiane.Praza@Sun.COM 
4290*7887SLiane.Praza@Sun.COM 	free(value_name);
4291*7887SLiane.Praza@Sun.COM 
4292*7887SLiane.Praza@Sun.COM 	if (*out == NULL)
4293*7887SLiane.Praza@Sun.COM 		return (-1);
4294*7887SLiane.Praza@Sun.COM 
4295*7887SLiane.Praza@Sun.COM 	return (strlen(*out));
4296*7887SLiane.Praza@Sun.COM }
4297*7887SLiane.Praza@Sun.COM 
4298*7887SLiane.Praza@Sun.COM /*
4299*7887SLiane.Praza@Sun.COM  * Templates error messages format, in human readable form.
4300*7887SLiane.Praza@Sun.COM  * Each line is one error item:
4301*7887SLiane.Praza@Sun.COM  *
4302*7887SLiane.Praza@Sun.COM  * prefix error message
4303*7887SLiane.Praza@Sun.COM  * 	FMRI="err->te_errs->tes_fmri"
4304*7887SLiane.Praza@Sun.COM  * 	Property group="err->te_pg_name"
4305*7887SLiane.Praza@Sun.COM  * 	Property name="err->te_prop_name"
4306*7887SLiane.Praza@Sun.COM  * 	expected value 1="err->te_ev1"
4307*7887SLiane.Praza@Sun.COM  * 	expected value 2="err->te_ev2"
4308*7887SLiane.Praza@Sun.COM  * 	actual value="err->te_actual"
4309*7887SLiane.Praza@Sun.COM  * 	Tempalte source="err->te_tmpl_fmri"
4310*7887SLiane.Praza@Sun.COM  * 	pg_pattern name="err->tmpl_pg_name"
4311*7887SLiane.Praza@Sun.COM  * 	pg_pattern type="err->tmpl_pg_type"
4312*7887SLiane.Praza@Sun.COM  * 	prop_pattern name="err->tmpl_prop_name"
4313*7887SLiane.Praza@Sun.COM  * 	prop_pattern type="err->tmpl_prop_type"
4314*7887SLiane.Praza@Sun.COM  *
4315*7887SLiane.Praza@Sun.COM  * To add a new error type, include scf_tmpl_error_type_t in libscf.h
4316*7887SLiane.Praza@Sun.COM  * add one entry in em_desc[], and update the functions pointed by the
4317*7887SLiane.Praza@Sun.COM  * _tmpl_error_access array with the new error code. Also, update the
4318*7887SLiane.Praza@Sun.COM  * scf_tmpl_error_* functions to provide access to desired
4319*7887SLiane.Praza@Sun.COM  * scf_tmpl_error_t fields.
4320*7887SLiane.Praza@Sun.COM  *
4321*7887SLiane.Praza@Sun.COM  * To add a new error item, add a new field to scf_tmpl_error_t, a new field
4322*7887SLiane.Praza@Sun.COM  * in _scf_tmpl_error_desc or a new non-error-dependent string, add a new entry
4323*7887SLiane.Praza@Sun.COM  * in _tmpl_error_access array and create the appropriate get_val, get_desc
4324*7887SLiane.Praza@Sun.COM  * functions.
4325*7887SLiane.Praza@Sun.COM  *
4326*7887SLiane.Praza@Sun.COM  * Changes to both the validation logic and the error types and items must
4327*7887SLiane.Praza@Sun.COM  * be coordinated with the code in svccfg to ensure both libscf and svccfg's
4328*7887SLiane.Praza@Sun.COM  * manifest validation validate the same things.
4329*7887SLiane.Praza@Sun.COM  */
4330*7887SLiane.Praza@Sun.COM 
4331*7887SLiane.Praza@Sun.COM /*
4332*7887SLiane.Praza@Sun.COM  * Container for all template errors on a validated object.
4333*7887SLiane.Praza@Sun.COM  */
4334*7887SLiane.Praza@Sun.COM struct scf_tmpl_errors {
4335*7887SLiane.Praza@Sun.COM 	int			tes_index;
4336*7887SLiane.Praza@Sun.COM 	int			tes_num_errs;
4337*7887SLiane.Praza@Sun.COM 	scf_tmpl_error_t	**tes_errs;
4338*7887SLiane.Praza@Sun.COM 	int			tes_errs_size;
4339*7887SLiane.Praza@Sun.COM 	const char		*tes_fmri;
4340*7887SLiane.Praza@Sun.COM 	const char		*tes_prefix;
4341*7887SLiane.Praza@Sun.COM 	int			tes_flag; /* if set, scf_tmpl_error_destroy */
4342*7887SLiane.Praza@Sun.COM 					    /* will free strings in tes_errs  */
4343*7887SLiane.Praza@Sun.COM };
4344*7887SLiane.Praza@Sun.COM 
4345*7887SLiane.Praza@Sun.COM /*
4346*7887SLiane.Praza@Sun.COM  * Templates error-dependent labels
4347*7887SLiane.Praza@Sun.COM  */
4348*7887SLiane.Praza@Sun.COM struct _scf_tmpl_error_desc {
4349*7887SLiane.Praza@Sun.COM 	const char *em_msg;
4350*7887SLiane.Praza@Sun.COM 	const char *em_ev1;
4351*7887SLiane.Praza@Sun.COM 	const char *em_ev2;
4352*7887SLiane.Praza@Sun.COM 	const char *em_actual;
4353*7887SLiane.Praza@Sun.COM };
4354*7887SLiane.Praza@Sun.COM 
4355*7887SLiane.Praza@Sun.COM /*
4356*7887SLiane.Praza@Sun.COM  * This array MUST be kept in synch with the template error definition of
4357*7887SLiane.Praza@Sun.COM  * scf_tmpl_error_type_t in libscf.h
4358*7887SLiane.Praza@Sun.COM  */
4359*7887SLiane.Praza@Sun.COM static struct _scf_tmpl_error_desc em_desc[] = {
4360*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_MISSING_PG */
4361*7887SLiane.Praza@Sun.COM 	{ "Required property group missing", "Name of missing property group",
4362*7887SLiane.Praza@Sun.COM 	    "Type of missing property group", NULL },
4363*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_WRONG_PG_TYPE */
4364*7887SLiane.Praza@Sun.COM 	{ "Property group has bad type", "Specified type", NULL,
4365*7887SLiane.Praza@Sun.COM 	    "Actual type" },
4366*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_MISSING_PROP */
4367*7887SLiane.Praza@Sun.COM 	{ "Required property missing", "Name of missing property", NULL, NULL },
4368*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_WRONG_PROP_TYPE */
4369*7887SLiane.Praza@Sun.COM 	{ "Property has bad type", "Specified property type", NULL,
4370*7887SLiane.Praza@Sun.COM 	    "Actual property type" },
4371*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_CARDINALITY_VIOLATION */
4372*7887SLiane.Praza@Sun.COM 	{ "Number of property values violates cardinality restriction",
4373*7887SLiane.Praza@Sun.COM 	    "Cardinality minimum", "Cardinality maximum",
4374*7887SLiane.Praza@Sun.COM 	    "Actual number of values" },
4375*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_VALUE_CONSTRAINT_VIOLATED */
4376*7887SLiane.Praza@Sun.COM 	{ "Property has illegal value", NULL, NULL, "Illegal value" },
4377*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_RANGE_VIOLATION */
4378*7887SLiane.Praza@Sun.COM 	{ "Property value is out of range", NULL, NULL, "Actual value" },
4379*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_PG_REDEFINE */
4380*7887SLiane.Praza@Sun.COM 	{ "Instance redefines pg_pattern", "Instance pg_pattern name",
4381*7887SLiane.Praza@Sun.COM 	    "Instance pg_pattern type", NULL },
4382*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_PROP_TYPE_MISMATCH */
4383*7887SLiane.Praza@Sun.COM 	{ "Property type and value type mismatch", NULL, NULL, "Value type" },
4384*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_VALUE_OUT_OF_RANGE */
4385*7887SLiane.Praza@Sun.COM 	{ "Value is out of range", NULL, NULL, "Value" },
4386*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_INVALID_VALUE */
4387*7887SLiane.Praza@Sun.COM 	{ "Value is not valid", NULL, NULL, "Value" },
4388*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_PG_PATTERN_CONFLICT */
4389*7887SLiane.Praza@Sun.COM 	{ "Conflicting pg_pattern specifications", "Template source",
4390*7887SLiane.Praza@Sun.COM 	    "pg_pattern name", "pg_pattern type" },
4391*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_PROP_PATTERN_CONFLICT */
4392*7887SLiane.Praza@Sun.COM 	{ "Conflicting prop_pattern specifications", "Template source",
4393*7887SLiane.Praza@Sun.COM 	    "prop_pattern name", "prop_pattern type" },
4394*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_GENERAL_REDEFINE */
4395*7887SLiane.Praza@Sun.COM 	{ "Service or instance pg_pattern redefines a global or restarter "
4396*7887SLiane.Praza@Sun.COM 	    "pg_pattern", "Template source", "pg_pattern name",
4397*7887SLiane.Praza@Sun.COM 	    "pg_pattern type" },
4398*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_INCLUDE_VALUES */
4399*7887SLiane.Praza@Sun.COM 	{ "Missing constraints or values for include_values element",
4400*7887SLiane.Praza@Sun.COM 	    "include_values type", NULL, NULL },
4401*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_PG_PATTERN_INCOMPLETE */
4402*7887SLiane.Praza@Sun.COM 	{ "Required pg_pattern is missing a name or type attribute",
4403*7887SLiane.Praza@Sun.COM 	    NULL, NULL, NULL },
4404*7887SLiane.Praza@Sun.COM 	/* SCF_TERR_PROP_PATTERN_INCOMPLETE */
4405*7887SLiane.Praza@Sun.COM 	{ "Required prop_pattern is missing a type attribute",
4406*7887SLiane.Praza@Sun.COM 	    NULL, NULL, NULL }
4407*7887SLiane.Praza@Sun.COM };
4408*7887SLiane.Praza@Sun.COM 
4409*7887SLiane.Praza@Sun.COM /*
4410*7887SLiane.Praza@Sun.COM  * Templates non error-dependent labels
4411*7887SLiane.Praza@Sun.COM  */
4412*7887SLiane.Praza@Sun.COM static const char *em_fmri = "FMRI";
4413*7887SLiane.Praza@Sun.COM static const char *em_pg_name = "Property group";
4414*7887SLiane.Praza@Sun.COM static const char *em_prop_name = "Property name";
4415*7887SLiane.Praza@Sun.COM static const char *em_tmpl_fmri = "Template source";
4416*7887SLiane.Praza@Sun.COM static const char *em_tmpl_pg_name = "pg_pattern name";
4417*7887SLiane.Praza@Sun.COM static const char *em_tmpl_pg_type = "pg_pattern type";
4418*7887SLiane.Praza@Sun.COM static const char *em_tmpl_prop_name = "prop_pattern name";
4419*7887SLiane.Praza@Sun.COM static const char *em_tmpl_prop_type = "prop_pattern type";
4420*7887SLiane.Praza@Sun.COM 
4421*7887SLiane.Praza@Sun.COM static const char *
4422*7887SLiane.Praza@Sun.COM _get_fmri_desc(scf_tmpl_error_t *err)
4423*7887SLiane.Praza@Sun.COM {
4424*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4425*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4426*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4427*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4428*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4429*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4430*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4431*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4432*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4433*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4434*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4435*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4436*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_fmri));
4437*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4438*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4439*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4440*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4441*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4442*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4443*7887SLiane.Praza@Sun.COM 	default:
4444*7887SLiane.Praza@Sun.COM 		return (NULL);
4445*7887SLiane.Praza@Sun.COM 	}
4446*7887SLiane.Praza@Sun.COM }
4447*7887SLiane.Praza@Sun.COM 
4448*7887SLiane.Praza@Sun.COM static const char *
4449*7887SLiane.Praza@Sun.COM _get_pg_name_desc(scf_tmpl_error_t *err)
4450*7887SLiane.Praza@Sun.COM {
4451*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4452*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4453*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4454*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4455*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4456*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4457*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4458*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_pg_name));
4459*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4460*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4461*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4462*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4463*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4464*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4465*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4466*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4467*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4468*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4469*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4470*7887SLiane.Praza@Sun.COM 	default:
4471*7887SLiane.Praza@Sun.COM 		return (NULL);
4472*7887SLiane.Praza@Sun.COM 	}
4473*7887SLiane.Praza@Sun.COM }
4474*7887SLiane.Praza@Sun.COM 
4475*7887SLiane.Praza@Sun.COM static const char *
4476*7887SLiane.Praza@Sun.COM _get_prop_name_desc(scf_tmpl_error_t *err)
4477*7887SLiane.Praza@Sun.COM {
4478*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4479*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4480*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4481*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4482*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4483*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_prop_name));
4484*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4485*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4486*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4487*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4488*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4489*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4490*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4491*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4492*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4493*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4494*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4495*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4496*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4497*7887SLiane.Praza@Sun.COM 	default:
4498*7887SLiane.Praza@Sun.COM 		return (NULL);
4499*7887SLiane.Praza@Sun.COM 	}
4500*7887SLiane.Praza@Sun.COM }
4501*7887SLiane.Praza@Sun.COM 
4502*7887SLiane.Praza@Sun.COM static const char *
4503*7887SLiane.Praza@Sun.COM _get_ev1_desc(scf_tmpl_error_t *err)
4504*7887SLiane.Praza@Sun.COM {
4505*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4506*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4507*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4508*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4509*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4510*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4511*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4512*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4513*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4514*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4515*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4516*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4517*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev1));
4518*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4519*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4520*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4521*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4522*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4523*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4524*7887SLiane.Praza@Sun.COM 	default:
4525*7887SLiane.Praza@Sun.COM 		return (NULL);
4526*7887SLiane.Praza@Sun.COM 	}
4527*7887SLiane.Praza@Sun.COM }
4528*7887SLiane.Praza@Sun.COM 
4529*7887SLiane.Praza@Sun.COM static const char *
4530*7887SLiane.Praza@Sun.COM _get_ev2_desc(scf_tmpl_error_t *err)
4531*7887SLiane.Praza@Sun.COM {
4532*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4533*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4534*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4535*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4536*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4537*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4538*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4539*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4540*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev2));
4541*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4542*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4543*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4544*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4545*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4546*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4547*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4548*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4549*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4550*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4551*7887SLiane.Praza@Sun.COM 	default:
4552*7887SLiane.Praza@Sun.COM 		return (NULL);
4553*7887SLiane.Praza@Sun.COM 	}
4554*7887SLiane.Praza@Sun.COM }
4555*7887SLiane.Praza@Sun.COM 
4556*7887SLiane.Praza@Sun.COM static const char *
4557*7887SLiane.Praza@Sun.COM _get_actual_desc(scf_tmpl_error_t *err)
4558*7887SLiane.Praza@Sun.COM {
4559*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4560*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4561*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4562*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4563*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4564*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4565*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4566*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4567*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4568*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4569*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4570*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4571*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4572*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4573*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN,
4574*7887SLiane.Praza@Sun.COM 		    em_desc[err->te_type].em_actual));
4575*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4576*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4577*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4578*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4579*7887SLiane.Praza@Sun.COM 	default:
4580*7887SLiane.Praza@Sun.COM 		return (NULL);
4581*7887SLiane.Praza@Sun.COM 	}
4582*7887SLiane.Praza@Sun.COM }
4583*7887SLiane.Praza@Sun.COM 
4584*7887SLiane.Praza@Sun.COM static const char *
4585*7887SLiane.Praza@Sun.COM _get_tmpl_fmri_desc(scf_tmpl_error_t *err)
4586*7887SLiane.Praza@Sun.COM {
4587*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4588*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4589*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4590*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4591*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4592*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4593*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4594*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4595*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4596*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4597*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4598*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4599*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4600*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4601*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4602*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4603*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4604*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4605*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_fmri));
4606*7887SLiane.Praza@Sun.COM 	default:
4607*7887SLiane.Praza@Sun.COM 		return (NULL);
4608*7887SLiane.Praza@Sun.COM 	}
4609*7887SLiane.Praza@Sun.COM }
4610*7887SLiane.Praza@Sun.COM 
4611*7887SLiane.Praza@Sun.COM static const char *
4612*7887SLiane.Praza@Sun.COM _get_tmpl_pg_name_desc(scf_tmpl_error_t *err)
4613*7887SLiane.Praza@Sun.COM {
4614*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4615*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4616*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4617*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4618*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4619*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4620*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4621*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4622*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4623*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4624*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4625*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4626*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4627*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4628*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4629*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4630*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4631*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4632*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_pg_name));
4633*7887SLiane.Praza@Sun.COM 	default:
4634*7887SLiane.Praza@Sun.COM 		return (NULL);
4635*7887SLiane.Praza@Sun.COM 	}
4636*7887SLiane.Praza@Sun.COM }
4637*7887SLiane.Praza@Sun.COM 
4638*7887SLiane.Praza@Sun.COM static const char *
4639*7887SLiane.Praza@Sun.COM _get_tmpl_pg_type_desc(scf_tmpl_error_t *err)
4640*7887SLiane.Praza@Sun.COM {
4641*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4642*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4643*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4644*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4645*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4646*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4647*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4648*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4649*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4650*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4651*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4652*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4653*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4654*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4655*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4656*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4657*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4658*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4659*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_pg_type));
4660*7887SLiane.Praza@Sun.COM 	default:
4661*7887SLiane.Praza@Sun.COM 		return (NULL);
4662*7887SLiane.Praza@Sun.COM 	}
4663*7887SLiane.Praza@Sun.COM }
4664*7887SLiane.Praza@Sun.COM 
4665*7887SLiane.Praza@Sun.COM static const char *
4666*7887SLiane.Praza@Sun.COM _get_tmpl_prop_name_desc(scf_tmpl_error_t *err)
4667*7887SLiane.Praza@Sun.COM {
4668*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4669*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4670*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4671*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4672*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4673*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4674*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4675*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4676*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4677*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4678*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4679*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4680*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_prop_name));
4681*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4682*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4683*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4684*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4685*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4686*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4687*7887SLiane.Praza@Sun.COM 	default:
4688*7887SLiane.Praza@Sun.COM 		return (NULL);
4689*7887SLiane.Praza@Sun.COM 	}
4690*7887SLiane.Praza@Sun.COM }
4691*7887SLiane.Praza@Sun.COM 
4692*7887SLiane.Praza@Sun.COM static const char *
4693*7887SLiane.Praza@Sun.COM _get_tmpl_prop_type_desc(scf_tmpl_error_t *err)
4694*7887SLiane.Praza@Sun.COM {
4695*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
4696*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
4697*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
4698*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
4699*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
4700*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
4701*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
4702*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
4703*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
4704*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_CONFLICT:
4705*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INCLUDE_VALUES:
4706*7887SLiane.Praza@Sun.COM 		return (dgettext(TEXT_DOMAIN, em_tmpl_prop_type));
4707*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
4708*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
4709*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
4710*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_CONFLICT:
4711*7887SLiane.Praza@Sun.COM 	case SCF_TERR_GENERAL_REDEFINE:
4712*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
4713*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
4714*7887SLiane.Praza@Sun.COM 	default:
4715*7887SLiane.Praza@Sun.COM 		return (NULL);
4716*7887SLiane.Praza@Sun.COM 	}
4717*7887SLiane.Praza@Sun.COM }
4718*7887SLiane.Praza@Sun.COM 
4719*7887SLiane.Praza@Sun.COM static const char *
4720*7887SLiane.Praza@Sun.COM _get_fmri_val(scf_tmpl_error_t *err)
4721*7887SLiane.Praza@Sun.COM {
4722*7887SLiane.Praza@Sun.COM 	assert(err != NULL && err->te_errs != NULL &&
4723*7887SLiane.Praza@Sun.COM 	    err->te_errs->tes_fmri != NULL);
4724*7887SLiane.Praza@Sun.COM 	return (err->te_errs->tes_fmri);
4725*7887SLiane.Praza@Sun.COM }
4726*7887SLiane.Praza@Sun.COM 
4727*7887SLiane.Praza@Sun.COM static const char *
4728*7887SLiane.Praza@Sun.COM _get_pg_name_val(scf_tmpl_error_t *err)
4729*7887SLiane.Praza@Sun.COM {
4730*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4731*7887SLiane.Praza@Sun.COM 	return (err->te_pg_name);
4732*7887SLiane.Praza@Sun.COM }
4733*7887SLiane.Praza@Sun.COM 
4734*7887SLiane.Praza@Sun.COM static const char *
4735*7887SLiane.Praza@Sun.COM _get_prop_name_val(scf_tmpl_error_t *err)
4736*7887SLiane.Praza@Sun.COM {
4737*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4738*7887SLiane.Praza@Sun.COM 	return (err->te_prop_name);
4739*7887SLiane.Praza@Sun.COM }
4740*7887SLiane.Praza@Sun.COM 
4741*7887SLiane.Praza@Sun.COM static const char *
4742*7887SLiane.Praza@Sun.COM _get_ev1_val(scf_tmpl_error_t *err)
4743*7887SLiane.Praza@Sun.COM {
4744*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4745*7887SLiane.Praza@Sun.COM 	return (err->te_ev1);
4746*7887SLiane.Praza@Sun.COM }
4747*7887SLiane.Praza@Sun.COM 
4748*7887SLiane.Praza@Sun.COM static const char *
4749*7887SLiane.Praza@Sun.COM _get_ev2_val(scf_tmpl_error_t *err)
4750*7887SLiane.Praza@Sun.COM {
4751*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4752*7887SLiane.Praza@Sun.COM 	return (err->te_ev2);
4753*7887SLiane.Praza@Sun.COM }
4754*7887SLiane.Praza@Sun.COM 
4755*7887SLiane.Praza@Sun.COM static const char *
4756*7887SLiane.Praza@Sun.COM _get_actual_val(scf_tmpl_error_t *err)
4757*7887SLiane.Praza@Sun.COM {
4758*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4759*7887SLiane.Praza@Sun.COM 	return (err->te_actual);
4760*7887SLiane.Praza@Sun.COM }
4761*7887SLiane.Praza@Sun.COM 
4762*7887SLiane.Praza@Sun.COM static const char *
4763*7887SLiane.Praza@Sun.COM _get_tmpl_fmri_val(scf_tmpl_error_t *err)
4764*7887SLiane.Praza@Sun.COM {
4765*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4766*7887SLiane.Praza@Sun.COM 	return (err->te_tmpl_fmri);
4767*7887SLiane.Praza@Sun.COM }
4768*7887SLiane.Praza@Sun.COM 
4769*7887SLiane.Praza@Sun.COM static const char *
4770*7887SLiane.Praza@Sun.COM _get_tmpl_pg_name_val(scf_tmpl_error_t *err)
4771*7887SLiane.Praza@Sun.COM {
4772*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4773*7887SLiane.Praza@Sun.COM 	return (err->te_tmpl_pg_name);
4774*7887SLiane.Praza@Sun.COM }
4775*7887SLiane.Praza@Sun.COM 
4776*7887SLiane.Praza@Sun.COM static const char *
4777*7887SLiane.Praza@Sun.COM _get_tmpl_pg_type_val(scf_tmpl_error_t *err)
4778*7887SLiane.Praza@Sun.COM {
4779*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4780*7887SLiane.Praza@Sun.COM 	return (err->te_tmpl_pg_type);
4781*7887SLiane.Praza@Sun.COM }
4782*7887SLiane.Praza@Sun.COM 
4783*7887SLiane.Praza@Sun.COM static const char *
4784*7887SLiane.Praza@Sun.COM _get_tmpl_prop_name_val(scf_tmpl_error_t *err)
4785*7887SLiane.Praza@Sun.COM {
4786*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4787*7887SLiane.Praza@Sun.COM 	return (err->te_tmpl_prop_name);
4788*7887SLiane.Praza@Sun.COM }
4789*7887SLiane.Praza@Sun.COM 
4790*7887SLiane.Praza@Sun.COM static const char *
4791*7887SLiane.Praza@Sun.COM _get_tmpl_prop_type_val(scf_tmpl_error_t *err)
4792*7887SLiane.Praza@Sun.COM {
4793*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
4794*7887SLiane.Praza@Sun.COM 	return (err->te_tmpl_prop_type);
4795*7887SLiane.Praza@Sun.COM }
4796*7887SLiane.Praza@Sun.COM 
4797*7887SLiane.Praza@Sun.COM /*
4798*7887SLiane.Praza@Sun.COM  * Templates error item retrival functions
4799*7887SLiane.Praza@Sun.COM  */
4800*7887SLiane.Praza@Sun.COM typedef const char *(*get_em)(scf_tmpl_error_t *);
4801*7887SLiane.Praza@Sun.COM 
4802*7887SLiane.Praza@Sun.COM /*
4803*7887SLiane.Praza@Sun.COM  * if new items (lines) are added to the templates error messages,
4804*7887SLiane.Praza@Sun.COM  * new entries in this array (and new fuctions) will be required.
4805*7887SLiane.Praza@Sun.COM  */
4806*7887SLiane.Praza@Sun.COM static struct _tmpl_error_access {
4807*7887SLiane.Praza@Sun.COM 	get_em get_desc;
4808*7887SLiane.Praza@Sun.COM 	get_em get_val;
4809*7887SLiane.Praza@Sun.COM } _tmpl_error_items[] = {
4810*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_fmri_desc, (get_em)_get_fmri_val },
4811*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_pg_name_desc, (get_em)_get_pg_name_val },
4812*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_prop_name_desc, (get_em)_get_prop_name_val },
4813*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_ev1_desc, (get_em)_get_ev1_val },
4814*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_ev2_desc, (get_em)_get_ev2_val },
4815*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_actual_desc, (get_em)_get_actual_val },
4816*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_fmri_desc, (get_em)_get_tmpl_fmri_val },
4817*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_pg_name_desc, (get_em)_get_tmpl_pg_name_val },
4818*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_pg_type_desc, (get_em)_get_tmpl_pg_type_val },
4819*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_prop_name_desc, (get_em)_get_tmpl_prop_name_val },
4820*7887SLiane.Praza@Sun.COM 	{ (get_em)_get_tmpl_prop_type_desc, (get_em)_get_tmpl_prop_type_val },
4821*7887SLiane.Praza@Sun.COM 	{ NULL }
4822*7887SLiane.Praza@Sun.COM };
4823*7887SLiane.Praza@Sun.COM 
4824*7887SLiane.Praza@Sun.COM /*
4825*7887SLiane.Praza@Sun.COM  * Allocate a new scf_tmpl_error_t and add it to the errs list provided.
4826*7887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
4827*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4828*7887SLiane.Praza@Sun.COM  */
4829*7887SLiane.Praza@Sun.COM static scf_tmpl_error_t *
4830*7887SLiane.Praza@Sun.COM _create_error(scf_tmpl_errors_t *errs)
4831*7887SLiane.Praza@Sun.COM {
4832*7887SLiane.Praza@Sun.COM 	scf_tmpl_error_t *ret;
4833*7887SLiane.Praza@Sun.COM 	scf_tmpl_error_t **saved_errs;
4834*7887SLiane.Praza@Sun.COM 
4835*7887SLiane.Praza@Sun.COM 	assert(errs != NULL);
4836*7887SLiane.Praza@Sun.COM 	ret = calloc(1, sizeof (scf_tmpl_error_t));
4837*7887SLiane.Praza@Sun.COM 	if (ret == NULL) {
4838*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4839*7887SLiane.Praza@Sun.COM 		return (NULL);
4840*7887SLiane.Praza@Sun.COM 	}
4841*7887SLiane.Praza@Sun.COM 
4842*7887SLiane.Praza@Sun.COM 	ret->te_errs = errs;
4843*7887SLiane.Praza@Sun.COM 
4844*7887SLiane.Praza@Sun.COM 	assert(errs->tes_num_errs <= errs->tes_errs_size);
4845*7887SLiane.Praza@Sun.COM 	if (errs->tes_num_errs == errs->tes_errs_size) {
4846*7887SLiane.Praza@Sun.COM 		/* Time to grow the pointer array. */
4847*7887SLiane.Praza@Sun.COM 		saved_errs = errs->tes_errs;
4848*7887SLiane.Praza@Sun.COM 		errs->tes_errs = calloc(2 * errs->tes_errs_size,
4849*7887SLiane.Praza@Sun.COM 		    sizeof (scf_tmpl_error_t *));
4850*7887SLiane.Praza@Sun.COM 		if (errs->tes_errs == NULL) {
4851*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4852*7887SLiane.Praza@Sun.COM 			errs->tes_errs = saved_errs;
4853*7887SLiane.Praza@Sun.COM 			free(ret);
4854*7887SLiane.Praza@Sun.COM 			return (NULL);
4855*7887SLiane.Praza@Sun.COM 		}
4856*7887SLiane.Praza@Sun.COM 		(void) memcpy(errs->tes_errs, saved_errs, errs->tes_errs_size *
4857*7887SLiane.Praza@Sun.COM 		    sizeof (scf_tmpl_error_t *));
4858*7887SLiane.Praza@Sun.COM 		errs->tes_errs_size = 2 * errs->tes_errs_size;
4859*7887SLiane.Praza@Sun.COM 		free(saved_errs);
4860*7887SLiane.Praza@Sun.COM 	}
4861*7887SLiane.Praza@Sun.COM 
4862*7887SLiane.Praza@Sun.COM 	errs->tes_errs[errs->tes_num_errs] = ret;
4863*7887SLiane.Praza@Sun.COM 	errs->tes_num_errs++;
4864*7887SLiane.Praza@Sun.COM 
4865*7887SLiane.Praza@Sun.COM 	return (ret);
4866*7887SLiane.Praza@Sun.COM }
4867*7887SLiane.Praza@Sun.COM 
4868*7887SLiane.Praza@Sun.COM /*
4869*7887SLiane.Praza@Sun.COM  *
4870*7887SLiane.Praza@Sun.COM  * If destroy_strings is set, scf_tmpl_errors_destroy will free the
4871*7887SLiane.Praza@Sun.COM  * strings in scf_tmpl_error_t entries.
4872*7887SLiane.Praza@Sun.COM  *
4873*7887SLiane.Praza@Sun.COM  * Returns NULL on failure.  Sets scf_error():
4874*7887SLiane.Praza@Sun.COM  *    SCF_ERROR_NO_MEMORY
4875*7887SLiane.Praza@Sun.COM  */
4876*7887SLiane.Praza@Sun.COM scf_tmpl_errors_t *
4877*7887SLiane.Praza@Sun.COM _scf_create_errors(const char *fmri, int destroy_strings)
4878*7887SLiane.Praza@Sun.COM {
4879*7887SLiane.Praza@Sun.COM 	scf_tmpl_errors_t *ret;
4880*7887SLiane.Praza@Sun.COM 	int errs_size = 20;
4881*7887SLiane.Praza@Sun.COM 
4882*7887SLiane.Praza@Sun.COM 	assert(fmri != NULL);
4883*7887SLiane.Praza@Sun.COM 
4884*7887SLiane.Praza@Sun.COM 	ret = calloc(1, sizeof (scf_tmpl_errors_t));
4885*7887SLiane.Praza@Sun.COM 	if (ret == NULL) {
4886*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4887*7887SLiane.Praza@Sun.COM 		return (NULL);
4888*7887SLiane.Praza@Sun.COM 	}
4889*7887SLiane.Praza@Sun.COM 
4890*7887SLiane.Praza@Sun.COM 	ret->tes_index = 0;
4891*7887SLiane.Praza@Sun.COM 	ret->tes_num_errs = 0;
4892*7887SLiane.Praza@Sun.COM 	if ((ret->tes_fmri = strdup(fmri)) == NULL) {
4893*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4894*7887SLiane.Praza@Sun.COM 		free(ret);
4895*7887SLiane.Praza@Sun.COM 		return (NULL);
4896*7887SLiane.Praza@Sun.COM 	}
4897*7887SLiane.Praza@Sun.COM 
4898*7887SLiane.Praza@Sun.COM 	ret->tes_prefix = strdup("");
4899*7887SLiane.Praza@Sun.COM 	if (ret->tes_prefix == NULL) {
4900*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4901*7887SLiane.Praza@Sun.COM 		free((char *)ret->tes_fmri);
4902*7887SLiane.Praza@Sun.COM 		free(ret);
4903*7887SLiane.Praza@Sun.COM 		return (NULL);
4904*7887SLiane.Praza@Sun.COM 	}
4905*7887SLiane.Praza@Sun.COM 	ret->tes_flag = destroy_strings;
4906*7887SLiane.Praza@Sun.COM 
4907*7887SLiane.Praza@Sun.COM 	/* Make space for a few errors. */
4908*7887SLiane.Praza@Sun.COM 	ret->tes_errs = calloc(errs_size, sizeof (scf_tmpl_error_t *));
4909*7887SLiane.Praza@Sun.COM 	if (ret->tes_errs == NULL) {
4910*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4911*7887SLiane.Praza@Sun.COM 		free((char *)ret->tes_fmri);
4912*7887SLiane.Praza@Sun.COM 		free((char *)ret->tes_prefix);
4913*7887SLiane.Praza@Sun.COM 		free(ret);
4914*7887SLiane.Praza@Sun.COM 		return (NULL);
4915*7887SLiane.Praza@Sun.COM 	}
4916*7887SLiane.Praza@Sun.COM 	ret->tes_errs_size = errs_size;
4917*7887SLiane.Praza@Sun.COM 
4918*7887SLiane.Praza@Sun.COM 	return (ret);
4919*7887SLiane.Praza@Sun.COM }
4920*7887SLiane.Praza@Sun.COM 
4921*7887SLiane.Praza@Sun.COM /*
4922*7887SLiane.Praza@Sun.COM  * return 0 on success, if fails set scf_error() to:
4923*7887SLiane.Praza@Sun.COM  *
4924*7887SLiane.Praza@Sun.COM  *    SCF_ERROR_NO_MEMORY
4925*7887SLiane.Praza@Sun.COM  */
4926*7887SLiane.Praza@Sun.COM int
4927*7887SLiane.Praza@Sun.COM _scf_tmpl_error_set_prefix(scf_tmpl_errors_t *errs, const char *prefix)
4928*7887SLiane.Praza@Sun.COM {
4929*7887SLiane.Praza@Sun.COM 	free((void *) errs->tes_prefix);
4930*7887SLiane.Praza@Sun.COM 	if (prefix == NULL)
4931*7887SLiane.Praza@Sun.COM 		errs->tes_prefix = strdup("");
4932*7887SLiane.Praza@Sun.COM 	else
4933*7887SLiane.Praza@Sun.COM 		errs->tes_prefix = strdup(prefix);
4934*7887SLiane.Praza@Sun.COM 	if (errs->tes_prefix == NULL) {
4935*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4936*7887SLiane.Praza@Sun.COM 		return (-1);
4937*7887SLiane.Praza@Sun.COM 	}
4938*7887SLiane.Praza@Sun.COM 	return (0);
4939*7887SLiane.Praza@Sun.COM }
4940*7887SLiane.Praza@Sun.COM 
4941*7887SLiane.Praza@Sun.COM /*
4942*7887SLiane.Praza@Sun.COM  *
4943*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
4944*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4945*7887SLiane.Praza@Sun.COM  */
4946*7887SLiane.Praza@Sun.COM int
4947*7887SLiane.Praza@Sun.COM _scf_tmpl_add_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
4948*7887SLiane.Praza@Sun.COM     const char *pg_name, const char *prop_name,
4949*7887SLiane.Praza@Sun.COM     const char *ev1, const char *ev2, const char *actual,
4950*7887SLiane.Praza@Sun.COM     const char *tmpl_fmri, const char *tmpl_pg_name, const char *tmpl_pg_type,
4951*7887SLiane.Praza@Sun.COM     const char *tmpl_prop_name, const char *tmpl_prop_type)
4952*7887SLiane.Praza@Sun.COM {
4953*7887SLiane.Praza@Sun.COM 	scf_tmpl_error_t *err;
4954*7887SLiane.Praza@Sun.COM 
4955*7887SLiane.Praza@Sun.COM 	assert(errs != NULL);
4956*7887SLiane.Praza@Sun.COM 	assert(tmpl_fmri != NULL);
4957*7887SLiane.Praza@Sun.COM 
4958*7887SLiane.Praza@Sun.COM 	err = _create_error(errs);
4959*7887SLiane.Praza@Sun.COM 	if (err == NULL)
4960*7887SLiane.Praza@Sun.COM 		return (-1);
4961*7887SLiane.Praza@Sun.COM 
4962*7887SLiane.Praza@Sun.COM 	err->te_type = type;
4963*7887SLiane.Praza@Sun.COM 	err->te_pg_name = pg_name;
4964*7887SLiane.Praza@Sun.COM 	err->te_prop_name = prop_name;
4965*7887SLiane.Praza@Sun.COM 	err->te_ev1 = ev1;
4966*7887SLiane.Praza@Sun.COM 	err->te_ev2 = ev2;
4967*7887SLiane.Praza@Sun.COM 	err->te_actual = actual;
4968*7887SLiane.Praza@Sun.COM 	err->te_tmpl_fmri = tmpl_fmri;
4969*7887SLiane.Praza@Sun.COM 	err->te_tmpl_pg_name = tmpl_pg_name;
4970*7887SLiane.Praza@Sun.COM 	err->te_tmpl_pg_type = tmpl_pg_type;
4971*7887SLiane.Praza@Sun.COM 	err->te_tmpl_prop_name = tmpl_prop_name;
4972*7887SLiane.Praza@Sun.COM 	err->te_tmpl_prop_type = tmpl_prop_type;
4973*7887SLiane.Praza@Sun.COM 
4974*7887SLiane.Praza@Sun.COM 	return (0);
4975*7887SLiane.Praza@Sun.COM }
4976*7887SLiane.Praza@Sun.COM 
4977*7887SLiane.Praza@Sun.COM /*
4978*7887SLiane.Praza@Sun.COM  * returns an allocated string that must be freed with free()
4979*7887SLiane.Praza@Sun.COM  * string contains converted 64-bit integer value
4980*7887SLiane.Praza@Sun.COM  * flag set for signed values
4981*7887SLiane.Praza@Sun.COM  * if fails return NULL and set scf_error() to:
4982*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
4983*7887SLiane.Praza@Sun.COM  */
4984*7887SLiane.Praza@Sun.COM static char *
4985*7887SLiane.Praza@Sun.COM _val_to_string(uint64_t val, int flag)
4986*7887SLiane.Praza@Sun.COM {
4987*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
4988*7887SLiane.Praza@Sun.COM 	char *buf;
4989*7887SLiane.Praza@Sun.COM 
4990*7887SLiane.Praza@Sun.COM 	buf = malloc(sz);
4991*7887SLiane.Praza@Sun.COM 	if (buf == NULL) {
4992*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
4993*7887SLiane.Praza@Sun.COM 		return (NULL);
4994*7887SLiane.Praza@Sun.COM 	}
4995*7887SLiane.Praza@Sun.COM 
4996*7887SLiane.Praza@Sun.COM 	if (flag == 0)
4997*7887SLiane.Praza@Sun.COM 		(void) snprintf(buf, sz, "%" PRIu64, val);
4998*7887SLiane.Praza@Sun.COM 	else
4999*7887SLiane.Praza@Sun.COM 		(void) snprintf(buf, sz, "%" PRIi64, (int64_t)val);
5000*7887SLiane.Praza@Sun.COM 
5001*7887SLiane.Praza@Sun.COM 	return (buf);
5002*7887SLiane.Praza@Sun.COM }
5003*7887SLiane.Praza@Sun.COM 
5004*7887SLiane.Praza@Sun.COM /*
5005*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5006*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5007*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5008*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5009*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5010*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5011*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5012*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5013*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5014*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5015*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5016*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5017*7887SLiane.Praza@Sun.COM  */
5018*7887SLiane.Praza@Sun.COM static int
5019*7887SLiane.Praza@Sun.COM _add_tmpl_missing_pg_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t)
5020*7887SLiane.Praza@Sun.COM {
5021*7887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
5022*7887SLiane.Praza@Sun.COM 	char *ev2 = NULL;
5023*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5024*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5025*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5026*7887SLiane.Praza@Sun.COM 
5027*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL)
5028*7887SLiane.Praza@Sun.COM 		return (-1);
5029*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &t_pg_name) == -1) {
5030*7887SLiane.Praza@Sun.COM 		goto cleanup;
5031*7887SLiane.Praza@Sun.COM 	}
5032*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &t_pg_type) == -1) {
5033*7887SLiane.Praza@Sun.COM 		goto cleanup;
5034*7887SLiane.Praza@Sun.COM 	}
5035*7887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_pg_name)) == NULL) {
5036*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5037*7887SLiane.Praza@Sun.COM 		goto cleanup;
5038*7887SLiane.Praza@Sun.COM 	}
5039*7887SLiane.Praza@Sun.COM 	if ((ev2 = strdup(t_pg_type)) == NULL) {
5040*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5041*7887SLiane.Praza@Sun.COM 		goto cleanup;
5042*7887SLiane.Praza@Sun.COM 	}
5043*7887SLiane.Praza@Sun.COM 
5044*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PG, NULL, NULL, ev1,
5045*7887SLiane.Praza@Sun.COM 	    ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL));
5046*7887SLiane.Praza@Sun.COM cleanup:
5047*7887SLiane.Praza@Sun.COM 	free(ev1);
5048*7887SLiane.Praza@Sun.COM 	free(ev2);
5049*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5050*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5051*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5052*7887SLiane.Praza@Sun.COM 	return (-1);
5053*7887SLiane.Praza@Sun.COM }
5054*7887SLiane.Praza@Sun.COM 
5055*7887SLiane.Praza@Sun.COM /*
5056*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5057*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5058*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5059*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5060*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5061*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5062*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5063*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5064*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5065*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5066*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5067*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5068*7887SLiane.Praza@Sun.COM  */
5069*7887SLiane.Praza@Sun.COM static int
5070*7887SLiane.Praza@Sun.COM _add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t,
5071*7887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg)
5072*7887SLiane.Praza@Sun.COM {
5073*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
5074*7887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
5075*7887SLiane.Praza@Sun.COM 	char *actual = NULL;
5076*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5077*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5078*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5079*7887SLiane.Praza@Sun.COM 
5080*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL)
5081*7887SLiane.Praza@Sun.COM 		return (-1);
5082*7887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(pg)) == NULL)
5083*7887SLiane.Praza@Sun.COM 		goto cleanup;
5084*7887SLiane.Praza@Sun.COM 	if ((actual = _scf_get_pg_type(pg)) == NULL)
5085*7887SLiane.Praza@Sun.COM 		goto cleanup;
5086*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &t_pg_name) == -1) {
5087*7887SLiane.Praza@Sun.COM 		goto cleanup;
5088*7887SLiane.Praza@Sun.COM 	}
5089*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &t_pg_type) == -1) {
5090*7887SLiane.Praza@Sun.COM 		goto cleanup;
5091*7887SLiane.Praza@Sun.COM 	}
5092*7887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_pg_type)) == NULL) {
5093*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5094*7887SLiane.Praza@Sun.COM 		goto cleanup;
5095*7887SLiane.Praza@Sun.COM 	}
5096*7887SLiane.Praza@Sun.COM 
5097*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PG_TYPE, pg_name, NULL,
5098*7887SLiane.Praza@Sun.COM 	    ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type, NULL, NULL));
5099*7887SLiane.Praza@Sun.COM cleanup:
5100*7887SLiane.Praza@Sun.COM 	free(pg_name);
5101*7887SLiane.Praza@Sun.COM 	free(ev1);
5102*7887SLiane.Praza@Sun.COM 	free(actual);
5103*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5104*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5105*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5106*7887SLiane.Praza@Sun.COM 	return (-1);
5107*7887SLiane.Praza@Sun.COM }
5108*7887SLiane.Praza@Sun.COM 
5109*7887SLiane.Praza@Sun.COM /*
5110*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5111*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5112*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5113*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5114*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5115*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5116*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5117*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5118*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5119*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5120*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5121*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5122*7887SLiane.Praza@Sun.COM  */
5123*7887SLiane.Praza@Sun.COM static int
5124*7887SLiane.Praza@Sun.COM _add_tmpl_missing_prop_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t,
5125*7887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt)
5126*7887SLiane.Praza@Sun.COM {
5127*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
5128*7887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
5129*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5130*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5131*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5132*7887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
5133*7887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
5134*7887SLiane.Praza@Sun.COM 
5135*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL)
5136*7887SLiane.Praza@Sun.COM 		return (-1);
5137*7887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(pg)) == NULL)
5138*7887SLiane.Praza@Sun.COM 		goto cleanup;
5139*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &t_pg_name) == -1) {
5140*7887SLiane.Praza@Sun.COM 		goto cleanup;
5141*7887SLiane.Praza@Sun.COM 	}
5142*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &t_pg_type) == -1) {
5143*7887SLiane.Praza@Sun.COM 		goto cleanup;
5144*7887SLiane.Praza@Sun.COM 	}
5145*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
5146*7887SLiane.Praza@Sun.COM 		goto cleanup;
5147*7887SLiane.Praza@Sun.COM 	}
5148*7887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
5149*7887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
5150*7887SLiane.Praza@Sun.COM 		free(t_prop_type);
5151*7887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
5152*7887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
5153*7887SLiane.Praza@Sun.COM 		goto cleanup;
5154*7887SLiane.Praza@Sun.COM 	}
5155*7887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
5156*7887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
5157*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5158*7887SLiane.Praza@Sun.COM 			goto cleanup;
5159*7887SLiane.Praza@Sun.COM 		}
5160*7887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_prop_name)) == NULL) {
5161*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5162*7887SLiane.Praza@Sun.COM 		goto cleanup;
5163*7887SLiane.Praza@Sun.COM 	}
5164*7887SLiane.Praza@Sun.COM 
5165*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PROP, pg_name, NULL,
5166*7887SLiane.Praza@Sun.COM 	    ev1, NULL, NULL, t_fmri, t_pg_name, t_pg_type, t_prop_name,
5167*7887SLiane.Praza@Sun.COM 	    t_prop_type));
5168*7887SLiane.Praza@Sun.COM cleanup:
5169*7887SLiane.Praza@Sun.COM 	free(pg_name);
5170*7887SLiane.Praza@Sun.COM 	free(ev1);
5171*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5172*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5173*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5174*7887SLiane.Praza@Sun.COM 	free(t_prop_name);
5175*7887SLiane.Praza@Sun.COM 	free(t_prop_type);
5176*7887SLiane.Praza@Sun.COM 	return (-1);
5177*7887SLiane.Praza@Sun.COM }
5178*7887SLiane.Praza@Sun.COM 
5179*7887SLiane.Praza@Sun.COM /*
5180*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5181*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5182*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5183*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5184*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5185*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5186*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5187*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5188*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5189*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5190*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5191*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5192*7887SLiane.Praza@Sun.COM  */
5193*7887SLiane.Praza@Sun.COM static int
5194*7887SLiane.Praza@Sun.COM _add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t *errs,
5195*7887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop)
5196*7887SLiane.Praza@Sun.COM {
5197*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
5198*7887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
5199*7887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
5200*7887SLiane.Praza@Sun.COM 	char *actual = NULL;
5201*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5202*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5203*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5204*7887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
5205*7887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
5206*7887SLiane.Praza@Sun.COM 
5207*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
5208*7887SLiane.Praza@Sun.COM 		return (-1);
5209*7887SLiane.Praza@Sun.COM 	if ((pg_name = _scf_get_pg_name(pg)) == NULL)
5210*7887SLiane.Praza@Sun.COM 		goto cleanup;
5211*7887SLiane.Praza@Sun.COM 	if ((prop_name = _scf_get_prop_name(prop)) == NULL)
5212*7887SLiane.Praza@Sun.COM 		goto cleanup;
5213*7887SLiane.Praza@Sun.COM 	if ((actual = _scf_get_prop_type(prop)) == NULL)
5214*7887SLiane.Praza@Sun.COM 		goto cleanup;
5215*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
5216*7887SLiane.Praza@Sun.COM 		goto cleanup;
5217*7887SLiane.Praza@Sun.COM 	}
5218*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
5219*7887SLiane.Praza@Sun.COM 		goto cleanup;
5220*7887SLiane.Praza@Sun.COM 	}
5221*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
5222*7887SLiane.Praza@Sun.COM 		goto cleanup;
5223*7887SLiane.Praza@Sun.COM 	}
5224*7887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
5225*7887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
5226*7887SLiane.Praza@Sun.COM 		free(t_prop_type);
5227*7887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
5228*7887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
5229*7887SLiane.Praza@Sun.COM 		goto cleanup;
5230*7887SLiane.Praza@Sun.COM 	}
5231*7887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
5232*7887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
5233*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5234*7887SLiane.Praza@Sun.COM 			goto cleanup;
5235*7887SLiane.Praza@Sun.COM 		}
5236*7887SLiane.Praza@Sun.COM 	if ((ev1 = strdup(t_prop_type)) == NULL) {
5237*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5238*7887SLiane.Praza@Sun.COM 		goto cleanup;
5239*7887SLiane.Praza@Sun.COM 	}
5240*7887SLiane.Praza@Sun.COM 
5241*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PROP_TYPE, pg_name,
5242*7887SLiane.Praza@Sun.COM 	    prop_name, ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type,
5243*7887SLiane.Praza@Sun.COM 	    t_prop_name, t_prop_type));
5244*7887SLiane.Praza@Sun.COM cleanup:
5245*7887SLiane.Praza@Sun.COM 	free(pg_name);
5246*7887SLiane.Praza@Sun.COM 	free(prop_name);
5247*7887SLiane.Praza@Sun.COM 	free(ev1);
5248*7887SLiane.Praza@Sun.COM 	free(actual);
5249*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5250*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5251*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5252*7887SLiane.Praza@Sun.COM 	free(t_prop_name);
5253*7887SLiane.Praza@Sun.COM 	free(t_prop_type);
5254*7887SLiane.Praza@Sun.COM 	return (-1);
5255*7887SLiane.Praza@Sun.COM }
5256*7887SLiane.Praza@Sun.COM 
5257*7887SLiane.Praza@Sun.COM /*
5258*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5259*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5260*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5261*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5262*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5263*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5264*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5265*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5266*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5267*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5268*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5269*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5270*7887SLiane.Praza@Sun.COM  */
5271*7887SLiane.Praza@Sun.COM static int
5272*7887SLiane.Praza@Sun.COM _add_tmpl_count_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
5273*7887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop,
5274*7887SLiane.Praza@Sun.COM     uint64_t count, uint64_t *min, uint64_t *max)
5275*7887SLiane.Praza@Sun.COM {
5276*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
5277*7887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
5278*7887SLiane.Praza@Sun.COM 	char *s_min = NULL;
5279*7887SLiane.Praza@Sun.COM 	char *s_max = NULL;
5280*7887SLiane.Praza@Sun.COM 	char *num = NULL;
5281*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5282*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5283*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5284*7887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
5285*7887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
5286*7887SLiane.Praza@Sun.COM 
5287*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
5288*7887SLiane.Praza@Sun.COM 		return (-1);
5289*7887SLiane.Praza@Sun.COM 	switch (type) {
5290*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
5291*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
5292*7887SLiane.Praza@Sun.COM 		if ((pg_name = _scf_get_pg_name(pg)) == NULL)
5293*7887SLiane.Praza@Sun.COM 			goto cleanup;
5294*7887SLiane.Praza@Sun.COM 		if ((prop_name = _scf_get_prop_name(prop)) == NULL)
5295*7887SLiane.Praza@Sun.COM 			goto cleanup;
5296*7887SLiane.Praza@Sun.COM 		break;
5297*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
5298*7887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
5299*7887SLiane.Praza@Sun.COM 		break;
5300*7887SLiane.Praza@Sun.COM 	}
5301*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
5302*7887SLiane.Praza@Sun.COM 		goto cleanup;
5303*7887SLiane.Praza@Sun.COM 	}
5304*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
5305*7887SLiane.Praza@Sun.COM 		goto cleanup;
5306*7887SLiane.Praza@Sun.COM 	}
5307*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
5308*7887SLiane.Praza@Sun.COM 		goto cleanup;
5309*7887SLiane.Praza@Sun.COM 	}
5310*7887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
5311*7887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
5312*7887SLiane.Praza@Sun.COM 		free(t_prop_type);
5313*7887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
5314*7887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
5315*7887SLiane.Praza@Sun.COM 		goto cleanup;
5316*7887SLiane.Praza@Sun.COM 	}
5317*7887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
5318*7887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
5319*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5320*7887SLiane.Praza@Sun.COM 			goto cleanup;
5321*7887SLiane.Praza@Sun.COM 		}
5322*7887SLiane.Praza@Sun.COM 	if (min == NULL) {
5323*7887SLiane.Praza@Sun.COM 		if ((s_min = strdup("")) == NULL) {
5324*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5325*7887SLiane.Praza@Sun.COM 			goto cleanup;
5326*7887SLiane.Praza@Sun.COM 		}
5327*7887SLiane.Praza@Sun.COM 	} else {
5328*7887SLiane.Praza@Sun.COM 		if ((s_min = _val_to_string(*min, 0)) == NULL) {
5329*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5330*7887SLiane.Praza@Sun.COM 			goto cleanup;
5331*7887SLiane.Praza@Sun.COM 		}
5332*7887SLiane.Praza@Sun.COM 	}
5333*7887SLiane.Praza@Sun.COM 	if (max == NULL) {
5334*7887SLiane.Praza@Sun.COM 		if ((s_max = strdup("")) == NULL) {
5335*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5336*7887SLiane.Praza@Sun.COM 			goto cleanup;
5337*7887SLiane.Praza@Sun.COM 		}
5338*7887SLiane.Praza@Sun.COM 	} else {
5339*7887SLiane.Praza@Sun.COM 		if ((s_max = _val_to_string(*max, 0)) == NULL) {
5340*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5341*7887SLiane.Praza@Sun.COM 			goto cleanup;
5342*7887SLiane.Praza@Sun.COM 		}
5343*7887SLiane.Praza@Sun.COM 	}
5344*7887SLiane.Praza@Sun.COM 	if ((num = _val_to_string(count, 0)) == NULL) {
5345*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5346*7887SLiane.Praza@Sun.COM 		goto cleanup;
5347*7887SLiane.Praza@Sun.COM 	}
5348*7887SLiane.Praza@Sun.COM 
5349*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min,
5350*7887SLiane.Praza@Sun.COM 	    s_max, num, t_fmri, t_pg_name, t_pg_type, t_prop_name,
5351*7887SLiane.Praza@Sun.COM 	    t_prop_type));
5352*7887SLiane.Praza@Sun.COM cleanup:
5353*7887SLiane.Praza@Sun.COM 	free(pg_name);
5354*7887SLiane.Praza@Sun.COM 	free(prop_name);
5355*7887SLiane.Praza@Sun.COM 	free(s_min);
5356*7887SLiane.Praza@Sun.COM 	free(s_max);
5357*7887SLiane.Praza@Sun.COM 	free(num);
5358*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5359*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5360*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5361*7887SLiane.Praza@Sun.COM 	free(t_prop_name);
5362*7887SLiane.Praza@Sun.COM 	free(t_prop_type);
5363*7887SLiane.Praza@Sun.COM 	return (-1);
5364*7887SLiane.Praza@Sun.COM }
5365*7887SLiane.Praza@Sun.COM 
5366*7887SLiane.Praza@Sun.COM /*
5367*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5368*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5369*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5370*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5371*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5372*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5373*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5374*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5375*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5376*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5377*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5378*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5379*7887SLiane.Praza@Sun.COM  */
5380*7887SLiane.Praza@Sun.COM static int
5381*7887SLiane.Praza@Sun.COM _add_tmpl_constraint_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
5382*7887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop,
5383*7887SLiane.Praza@Sun.COM     scf_value_t *val)
5384*7887SLiane.Praza@Sun.COM {
5385*7887SLiane.Praza@Sun.COM 	scf_type_t val_type;
5386*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
5387*7887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
5388*7887SLiane.Praza@Sun.COM 	char *value = NULL;
5389*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5390*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5391*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5392*7887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
5393*7887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
5394*7887SLiane.Praza@Sun.COM 
5395*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
5396*7887SLiane.Praza@Sun.COM 		return (-1);
5397*7887SLiane.Praza@Sun.COM 	switch (type) {
5398*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
5399*7887SLiane.Praza@Sun.COM 		if ((pg_name = _scf_get_pg_name(pg)) == NULL)
5400*7887SLiane.Praza@Sun.COM 			goto cleanup;
5401*7887SLiane.Praza@Sun.COM 		if ((prop_name = _scf_get_prop_name(prop)) == NULL)
5402*7887SLiane.Praza@Sun.COM 			goto cleanup;
5403*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
5404*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
5405*7887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
5406*7887SLiane.Praza@Sun.COM 		if ((value = _scf_value_get_as_string(val)) == NULL)
5407*7887SLiane.Praza@Sun.COM 			goto cleanup;
5408*7887SLiane.Praza@Sun.COM 		break;
5409*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
5410*7887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
5411*7887SLiane.Praza@Sun.COM 		/* use value for value type */
5412*7887SLiane.Praza@Sun.COM 		val_type = scf_value_type(val);
5413*7887SLiane.Praza@Sun.COM 		if ((value = strdup(scf_type_to_string(val_type))) ==
5414*7887SLiane.Praza@Sun.COM 		    NULL) {
5415*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5416*7887SLiane.Praza@Sun.COM 			goto cleanup;
5417*7887SLiane.Praza@Sun.COM 		}
5418*7887SLiane.Praza@Sun.COM 		break;
5419*7887SLiane.Praza@Sun.COM 	}
5420*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
5421*7887SLiane.Praza@Sun.COM 		goto cleanup;
5422*7887SLiane.Praza@Sun.COM 	}
5423*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
5424*7887SLiane.Praza@Sun.COM 		goto cleanup;
5425*7887SLiane.Praza@Sun.COM 	}
5426*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
5427*7887SLiane.Praza@Sun.COM 		goto cleanup;
5428*7887SLiane.Praza@Sun.COM 	}
5429*7887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
5430*7887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
5431*7887SLiane.Praza@Sun.COM 		free(t_prop_type);
5432*7887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
5433*7887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
5434*7887SLiane.Praza@Sun.COM 		goto cleanup;
5435*7887SLiane.Praza@Sun.COM 	}
5436*7887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
5437*7887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
5438*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5439*7887SLiane.Praza@Sun.COM 			goto cleanup;
5440*7887SLiane.Praza@Sun.COM 		}
5441*7887SLiane.Praza@Sun.COM 
5442*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, NULL, NULL,
5443*7887SLiane.Praza@Sun.COM 	    value, t_fmri, t_pg_name, t_pg_type, t_prop_name, t_prop_type));
5444*7887SLiane.Praza@Sun.COM cleanup:
5445*7887SLiane.Praza@Sun.COM 	assert(scf_error() != SCF_ERROR_NOT_SET);
5446*7887SLiane.Praza@Sun.COM 	free(pg_name);
5447*7887SLiane.Praza@Sun.COM 	free(prop_name);
5448*7887SLiane.Praza@Sun.COM 	free(value);
5449*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5450*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5451*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5452*7887SLiane.Praza@Sun.COM 	free(t_prop_name);
5453*7887SLiane.Praza@Sun.COM 	free(t_prop_type);
5454*7887SLiane.Praza@Sun.COM 	return (-1);
5455*7887SLiane.Praza@Sun.COM }
5456*7887SLiane.Praza@Sun.COM 
5457*7887SLiane.Praza@Sun.COM /*
5458*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5459*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5460*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5461*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5462*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5463*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5464*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5465*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5466*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5467*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5468*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5469*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5470*7887SLiane.Praza@Sun.COM  */
5471*7887SLiane.Praza@Sun.COM static int
5472*7887SLiane.Praza@Sun.COM _add_tmpl_int_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type,
5473*7887SLiane.Praza@Sun.COM     scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop,
5474*7887SLiane.Praza@Sun.COM     int64_t val, int64_t *min, int64_t *max)
5475*7887SLiane.Praza@Sun.COM {
5476*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
5477*7887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
5478*7887SLiane.Praza@Sun.COM 	char *s_min = NULL;
5479*7887SLiane.Praza@Sun.COM 	char *s_max = NULL;
5480*7887SLiane.Praza@Sun.COM 	char *value = NULL;
5481*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5482*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5483*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5484*7887SLiane.Praza@Sun.COM 	char *t_prop_name = NULL;
5485*7887SLiane.Praza@Sun.COM 	char *t_prop_type = NULL;
5486*7887SLiane.Praza@Sun.COM 
5487*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
5488*7887SLiane.Praza@Sun.COM 		return (-1);
5489*7887SLiane.Praza@Sun.COM 
5490*7887SLiane.Praza@Sun.COM 	switch (type) {
5491*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
5492*7887SLiane.Praza@Sun.COM 		if ((pg_name = _scf_get_pg_name(pg)) == NULL)
5493*7887SLiane.Praza@Sun.COM 			goto cleanup;
5494*7887SLiane.Praza@Sun.COM 		if ((prop_name = _scf_get_prop_name(prop)) == NULL)
5495*7887SLiane.Praza@Sun.COM 			goto cleanup;
5496*7887SLiane.Praza@Sun.COM 		break;
5497*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
5498*7887SLiane.Praza@Sun.COM 		/* keep pg_name = NULL and prop_name = NULL */
5499*7887SLiane.Praza@Sun.COM 		break;
5500*7887SLiane.Praza@Sun.COM 	}
5501*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) {
5502*7887SLiane.Praza@Sun.COM 		goto cleanup;
5503*7887SLiane.Praza@Sun.COM 	}
5504*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) {
5505*7887SLiane.Praza@Sun.COM 		goto cleanup;
5506*7887SLiane.Praza@Sun.COM 	}
5507*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) {
5508*7887SLiane.Praza@Sun.COM 		goto cleanup;
5509*7887SLiane.Praza@Sun.COM 	}
5510*7887SLiane.Praza@Sun.COM 	t_prop_type = _scf_read_tmpl_prop_type_as_string(pt);
5511*7887SLiane.Praza@Sun.COM 	if (t_prop_type != NULL && t_prop_type[0] == '\0') {
5512*7887SLiane.Praza@Sun.COM 		free(t_prop_type);
5513*7887SLiane.Praza@Sun.COM 		t_prop_type = NULL;
5514*7887SLiane.Praza@Sun.COM 	} else if (t_prop_type == NULL) {
5515*7887SLiane.Praza@Sun.COM 		goto cleanup;
5516*7887SLiane.Praza@Sun.COM 	}
5517*7887SLiane.Praza@Sun.COM 	if (t_prop_type == NULL)
5518*7887SLiane.Praza@Sun.COM 		if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) {
5519*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5520*7887SLiane.Praza@Sun.COM 			goto cleanup;
5521*7887SLiane.Praza@Sun.COM 		}
5522*7887SLiane.Praza@Sun.COM 	if (min == NULL) {
5523*7887SLiane.Praza@Sun.COM 		if ((s_min = strdup("")) == NULL) {
5524*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5525*7887SLiane.Praza@Sun.COM 			goto cleanup;
5526*7887SLiane.Praza@Sun.COM 		}
5527*7887SLiane.Praza@Sun.COM 	} else {
5528*7887SLiane.Praza@Sun.COM 		if ((s_min = _val_to_string(*((uint64_t *)min), 1)) == NULL) {
5529*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5530*7887SLiane.Praza@Sun.COM 			goto cleanup;
5531*7887SLiane.Praza@Sun.COM 		}
5532*7887SLiane.Praza@Sun.COM 	}
5533*7887SLiane.Praza@Sun.COM 	if (max == NULL) {
5534*7887SLiane.Praza@Sun.COM 		if ((s_max = strdup("")) == NULL) {
5535*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5536*7887SLiane.Praza@Sun.COM 			goto cleanup;
5537*7887SLiane.Praza@Sun.COM 		}
5538*7887SLiane.Praza@Sun.COM 	} else {
5539*7887SLiane.Praza@Sun.COM 		if ((s_max = _val_to_string(*((uint64_t *)max), 1)) == NULL) {
5540*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5541*7887SLiane.Praza@Sun.COM 			goto cleanup;
5542*7887SLiane.Praza@Sun.COM 		}
5543*7887SLiane.Praza@Sun.COM 	}
5544*7887SLiane.Praza@Sun.COM 	if ((value = _val_to_string((uint64_t)val, 1)) == NULL) {
5545*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5546*7887SLiane.Praza@Sun.COM 		goto cleanup;
5547*7887SLiane.Praza@Sun.COM 	}
5548*7887SLiane.Praza@Sun.COM 
5549*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min,
5550*7887SLiane.Praza@Sun.COM 	    s_max, value, t_fmri, t_pg_name, t_pg_type, t_prop_name,
5551*7887SLiane.Praza@Sun.COM 	    t_prop_type));
5552*7887SLiane.Praza@Sun.COM cleanup:
5553*7887SLiane.Praza@Sun.COM 	free(pg_name);
5554*7887SLiane.Praza@Sun.COM 	free(prop_name);
5555*7887SLiane.Praza@Sun.COM 	free(s_min);
5556*7887SLiane.Praza@Sun.COM 	free(s_max);
5557*7887SLiane.Praza@Sun.COM 	free(value);
5558*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5559*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5560*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5561*7887SLiane.Praza@Sun.COM 	free(t_prop_name);
5562*7887SLiane.Praza@Sun.COM 	free(t_prop_type);
5563*7887SLiane.Praza@Sun.COM 	return (-1);
5564*7887SLiane.Praza@Sun.COM }
5565*7887SLiane.Praza@Sun.COM 
5566*7887SLiane.Praza@Sun.COM /*
5567*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5568*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5569*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5570*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5571*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5572*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5573*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5574*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5575*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5576*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5577*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5578*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5579*7887SLiane.Praza@Sun.COM  */
5580*7887SLiane.Praza@Sun.COM static int
5581*7887SLiane.Praza@Sun.COM _add_tmpl_pg_redefine_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t,
5582*7887SLiane.Praza@Sun.COM     scf_pg_tmpl_t *r)
5583*7887SLiane.Praza@Sun.COM {
5584*7887SLiane.Praza@Sun.COM 	char *ev1 = NULL;
5585*7887SLiane.Praza@Sun.COM 	char *ev2 = NULL;
5586*7887SLiane.Praza@Sun.COM 	char *t_fmri = NULL;
5587*7887SLiane.Praza@Sun.COM 	char *t_pg_name = NULL;
5588*7887SLiane.Praza@Sun.COM 	char *t_pg_type = NULL;
5589*7887SLiane.Praza@Sun.COM 
5590*7887SLiane.Praza@Sun.COM 	if ((t_fmri = _scf_tmpl_get_fmri(r)) == NULL)
5591*7887SLiane.Praza@Sun.COM 		return (-1);
5592*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(r, &t_pg_name) == -1) {
5593*7887SLiane.Praza@Sun.COM 		goto cleanup;
5594*7887SLiane.Praza@Sun.COM 	}
5595*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(r, &t_pg_type) == -1) {
5596*7887SLiane.Praza@Sun.COM 		goto cleanup;
5597*7887SLiane.Praza@Sun.COM 	}
5598*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_name(t, &ev1) == -1) {
5599*7887SLiane.Praza@Sun.COM 		goto cleanup;
5600*7887SLiane.Praza@Sun.COM 	}
5601*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &ev2) == -1) {
5602*7887SLiane.Praza@Sun.COM 		goto cleanup;
5603*7887SLiane.Praza@Sun.COM 	}
5604*7887SLiane.Praza@Sun.COM 
5605*7887SLiane.Praza@Sun.COM 	return (_scf_tmpl_add_error(errs, SCF_TERR_PG_REDEFINE, NULL, NULL,
5606*7887SLiane.Praza@Sun.COM 	    ev1, ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL));
5607*7887SLiane.Praza@Sun.COM cleanup:
5608*7887SLiane.Praza@Sun.COM 	free(ev1);
5609*7887SLiane.Praza@Sun.COM 	free(ev2);
5610*7887SLiane.Praza@Sun.COM 	free(t_fmri);
5611*7887SLiane.Praza@Sun.COM 	free(t_pg_name);
5612*7887SLiane.Praza@Sun.COM 	free(t_pg_type);
5613*7887SLiane.Praza@Sun.COM 	return (-1);
5614*7887SLiane.Praza@Sun.COM }
5615*7887SLiane.Praza@Sun.COM 
5616*7887SLiane.Praza@Sun.COM /*
5617*7887SLiane.Praza@Sun.COM  * return 0 if value is within count ranges constraint.
5618*7887SLiane.Praza@Sun.COM  * return -1 otherwise
5619*7887SLiane.Praza@Sun.COM  */
5620*7887SLiane.Praza@Sun.COM static int
5621*7887SLiane.Praza@Sun.COM _check_count_ranges(scf_count_ranges_t *cr, uint64_t v)
5622*7887SLiane.Praza@Sun.COM {
5623*7887SLiane.Praza@Sun.COM 	int i;
5624*7887SLiane.Praza@Sun.COM 
5625*7887SLiane.Praza@Sun.COM 	for (i = 0; i < cr->scr_num_ranges; ++i) {
5626*7887SLiane.Praza@Sun.COM 		if (v >= cr->scr_min[i] &&
5627*7887SLiane.Praza@Sun.COM 		    v <= cr->scr_max[i]) {
5628*7887SLiane.Praza@Sun.COM 			/* value is within ranges constraint */
5629*7887SLiane.Praza@Sun.COM 			return (0);
5630*7887SLiane.Praza@Sun.COM 		}
5631*7887SLiane.Praza@Sun.COM 	}
5632*7887SLiane.Praza@Sun.COM 	return (-1);
5633*7887SLiane.Praza@Sun.COM }
5634*7887SLiane.Praza@Sun.COM 
5635*7887SLiane.Praza@Sun.COM /*
5636*7887SLiane.Praza@Sun.COM  * return 0 if value is within count ranges constraint.
5637*7887SLiane.Praza@Sun.COM  * return -1 otherwise
5638*7887SLiane.Praza@Sun.COM  */
5639*7887SLiane.Praza@Sun.COM static int
5640*7887SLiane.Praza@Sun.COM _check_int_ranges(scf_int_ranges_t *ir, int64_t v)
5641*7887SLiane.Praza@Sun.COM {
5642*7887SLiane.Praza@Sun.COM 	int i;
5643*7887SLiane.Praza@Sun.COM 
5644*7887SLiane.Praza@Sun.COM 	for (i = 0; i < ir->sir_num_ranges; ++i) {
5645*7887SLiane.Praza@Sun.COM 		if (v >= ir->sir_min[i] &&
5646*7887SLiane.Praza@Sun.COM 		    v <= ir->sir_max[i]) {
5647*7887SLiane.Praza@Sun.COM 			/* value is within integer ranges constraint */
5648*7887SLiane.Praza@Sun.COM 			return (0);
5649*7887SLiane.Praza@Sun.COM 		}
5650*7887SLiane.Praza@Sun.COM 	}
5651*7887SLiane.Praza@Sun.COM 	return (-1);
5652*7887SLiane.Praza@Sun.COM }
5653*7887SLiane.Praza@Sun.COM 
5654*7887SLiane.Praza@Sun.COM /*
5655*7887SLiane.Praza@Sun.COM  * int _value_in_constraint()
5656*7887SLiane.Praza@Sun.COM  *
5657*7887SLiane.Praza@Sun.COM  * Checks whether the supplied value violates any of the constraints
5658*7887SLiane.Praza@Sun.COM  * specified in the supplied property template.  If it does, an appropriate
5659*7887SLiane.Praza@Sun.COM  * error is appended to "errs".  pg and prop, if supplied, are used to
5660*7887SLiane.Praza@Sun.COM  * augment the information in the error.  Returns 0 on success.
5661*7887SLiane.Praza@Sun.COM  *
5662*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
5663*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5664*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5665*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5666*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5667*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5668*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
5669*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5670*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5671*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5672*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5673*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5674*7887SLiane.Praza@Sun.COM  */
5675*7887SLiane.Praza@Sun.COM static int
5676*7887SLiane.Praza@Sun.COM _value_in_constraint(scf_propertygroup_t *pg, scf_property_t *prop,
5677*7887SLiane.Praza@Sun.COM     const scf_prop_tmpl_t *pt, scf_value_t *value, scf_tmpl_errors_t *errs)
5678*7887SLiane.Praza@Sun.COM {
5679*7887SLiane.Praza@Sun.COM 	scf_type_t type, tmpl_type;
5680*7887SLiane.Praza@Sun.COM 	scf_values_t vals;
5681*7887SLiane.Praza@Sun.COM 	scf_tmpl_error_type_t terr_type;
5682*7887SLiane.Praza@Sun.COM 	uint64_t v_count;
5683*7887SLiane.Praza@Sun.COM 	int64_t v_int;
5684*7887SLiane.Praza@Sun.COM 	char *vstr;
5685*7887SLiane.Praza@Sun.COM 	ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
5686*7887SLiane.Praza@Sun.COM 	ssize_t ret = 0;
5687*7887SLiane.Praza@Sun.COM 	char **constraints;
5688*7887SLiane.Praza@Sun.COM 	int n = 0;
5689*7887SLiane.Praza@Sun.COM 	int r;
5690*7887SLiane.Praza@Sun.COM 	int err_flag = 0;
5691*7887SLiane.Praza@Sun.COM 	scf_count_ranges_t cr;
5692*7887SLiane.Praza@Sun.COM 	scf_int_ranges_t ir;
5693*7887SLiane.Praza@Sun.COM 
5694*7887SLiane.Praza@Sun.COM 	type = scf_value_type(value);
5695*7887SLiane.Praza@Sun.COM 	if (type == SCF_TYPE_INVALID) {
5696*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
5697*7887SLiane.Praza@Sun.COM 		return (-1);
5698*7887SLiane.Praza@Sun.COM 	}
5699*7887SLiane.Praza@Sun.COM 
5700*7887SLiane.Praza@Sun.COM 	/* Check if template type matches value type. */
5701*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) {
5702*7887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND)
5703*7887SLiane.Praza@Sun.COM 			/* type is not wildcarded */
5704*7887SLiane.Praza@Sun.COM 			return (-1);
5705*7887SLiane.Praza@Sun.COM 	} else if (tmpl_type != type) {
5706*7887SLiane.Praza@Sun.COM 		if (errs != NULL) {
5707*7887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL) {
5708*7887SLiane.Praza@Sun.COM 				if (_add_tmpl_constraint_error(errs,
5709*7887SLiane.Praza@Sun.COM 				    SCF_TERR_PROP_TYPE_MISMATCH, NULL, pt,
5710*7887SLiane.Praza@Sun.COM 				    NULL, value) == -1)
5711*7887SLiane.Praza@Sun.COM 					return (-1);
5712*7887SLiane.Praza@Sun.COM 			} else {
5713*7887SLiane.Praza@Sun.COM 				if (_add_tmpl_wrong_prop_type_error(errs, pg,
5714*7887SLiane.Praza@Sun.COM 				    pt, prop) == -1)
5715*7887SLiane.Praza@Sun.COM 					return (-1);
5716*7887SLiane.Praza@Sun.COM 			}
5717*7887SLiane.Praza@Sun.COM 		}
5718*7887SLiane.Praza@Sun.COM 		return (1);
5719*7887SLiane.Praza@Sun.COM 	}
5720*7887SLiane.Praza@Sun.COM 
5721*7887SLiane.Praza@Sun.COM 	/* Numeric values should be checked against any range constraints. */
5722*7887SLiane.Praza@Sun.COM 	switch (type) {
5723*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_COUNT:
5724*7887SLiane.Praza@Sun.COM 		r = scf_value_get_count(value, &v_count);
5725*7887SLiane.Praza@Sun.COM 		assert(r == 0);
5726*7887SLiane.Praza@Sun.COM 
5727*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_value_count_range_constraints(pt, &cr) != 0) {
5728*7887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
5729*7887SLiane.Praza@Sun.COM 				break;
5730*7887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
5731*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
5732*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
5733*7887SLiane.Praza@Sun.COM 			return (-1);
5734*7887SLiane.Praza@Sun.COM 		} else {
5735*7887SLiane.Praza@Sun.COM 			if (_check_count_ranges(&cr, v_count) == 0) {
5736*7887SLiane.Praza@Sun.COM 				/* value is within ranges constraint */
5737*7887SLiane.Praza@Sun.COM 				scf_count_ranges_destroy(&cr);
5738*7887SLiane.Praza@Sun.COM 				return (0);
5739*7887SLiane.Praza@Sun.COM 			}
5740*7887SLiane.Praza@Sun.COM 			scf_count_ranges_destroy(&cr);
5741*7887SLiane.Praza@Sun.COM 		}
5742*7887SLiane.Praza@Sun.COM 
5743*7887SLiane.Praza@Sun.COM 		/*
5744*7887SLiane.Praza@Sun.COM 		 * If we get here, we have a possible constraint
5745*7887SLiane.Praza@Sun.COM 		 * violation.
5746*7887SLiane.Praza@Sun.COM 		 */
5747*7887SLiane.Praza@Sun.COM 		err_flag |= 0x1; /* RANGE_VIOLATION, count */
5748*7887SLiane.Praza@Sun.COM 		break;
5749*7887SLiane.Praza@Sun.COM 	case SCF_TYPE_INTEGER:
5750*7887SLiane.Praza@Sun.COM 		if (scf_value_get_integer(value, &v_int) != 0)
5751*7887SLiane.Praza@Sun.COM 			assert(0);
5752*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_value_int_range_constraints(pt, &ir) != 0) {
5753*7887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
5754*7887SLiane.Praza@Sun.COM 				break;
5755*7887SLiane.Praza@Sun.COM 			if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED)
5756*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
5757*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
5758*7887SLiane.Praza@Sun.COM 			return (-1);
5759*7887SLiane.Praza@Sun.COM 		} else {
5760*7887SLiane.Praza@Sun.COM 			if (_check_int_ranges(&ir, v_int) == 0) {
5761*7887SLiane.Praza@Sun.COM 				/* value is within ranges constraint */
5762*7887SLiane.Praza@Sun.COM 				scf_int_ranges_destroy(&ir);
5763*7887SLiane.Praza@Sun.COM 				return (0);
5764*7887SLiane.Praza@Sun.COM 			}
5765*7887SLiane.Praza@Sun.COM 			scf_int_ranges_destroy(&ir);
5766*7887SLiane.Praza@Sun.COM 		}
5767*7887SLiane.Praza@Sun.COM 		/*
5768*7887SLiane.Praza@Sun.COM 		 * If we get here, we have a possible constraint
5769*7887SLiane.Praza@Sun.COM 		 * violation.
5770*7887SLiane.Praza@Sun.COM 		 */
5771*7887SLiane.Praza@Sun.COM 		err_flag |= 0x2; /* RANGE_VIOLATION, integer */
5772*7887SLiane.Praza@Sun.COM 		break;
5773*7887SLiane.Praza@Sun.COM 	default:
5774*7887SLiane.Praza@Sun.COM 		break;
5775*7887SLiane.Praza@Sun.COM 	}
5776*7887SLiane.Praza@Sun.COM 
5777*7887SLiane.Praza@Sun.COM 	vstr = malloc(sz);
5778*7887SLiane.Praza@Sun.COM 	if (vstr == NULL) {
5779*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
5780*7887SLiane.Praza@Sun.COM 		return (-1);
5781*7887SLiane.Praza@Sun.COM 	}
5782*7887SLiane.Praza@Sun.COM 
5783*7887SLiane.Praza@Sun.COM 	/*
5784*7887SLiane.Praza@Sun.COM 	 * If a set of names is provided, confirm value has one of
5785*7887SLiane.Praza@Sun.COM 	 * those names.
5786*7887SLiane.Praza@Sun.COM 	 */
5787*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_value_name_constraints(pt, &vals) != 0) {
5788*7887SLiane.Praza@Sun.COM 		free(vstr);
5789*7887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
5790*7887SLiane.Praza@Sun.COM 			return (-1);
5791*7887SLiane.Praza@Sun.COM 		}
5792*7887SLiane.Praza@Sun.COM 	} else {
5793*7887SLiane.Praza@Sun.COM 		r = scf_value_get_as_string_typed(value, type, vstr, sz);
5794*7887SLiane.Praza@Sun.COM 
5795*7887SLiane.Praza@Sun.COM 		/*
5796*7887SLiane.Praza@Sun.COM 		 * All errors (INVALID_ARGUMENT, NOT_SET, TYPE_MISMATCH)
5797*7887SLiane.Praza@Sun.COM 		 * should be impossible or already caught above.
5798*7887SLiane.Praza@Sun.COM 		 */
5799*7887SLiane.Praza@Sun.COM 		assert(r > 0);
5800*7887SLiane.Praza@Sun.COM 
5801*7887SLiane.Praza@Sun.COM 		constraints = vals.values.v_astring;
5802*7887SLiane.Praza@Sun.COM 		for (n = 0; constraints[n] != NULL; ++n) {
5803*7887SLiane.Praza@Sun.COM 			if (strcmp(constraints[n], vstr) == 0) {
5804*7887SLiane.Praza@Sun.COM 				/* value is within constraint */
5805*7887SLiane.Praza@Sun.COM 				scf_values_destroy(&vals);
5806*7887SLiane.Praza@Sun.COM 				free(vstr);
5807*7887SLiane.Praza@Sun.COM 				return (0);
5808*7887SLiane.Praza@Sun.COM 			}
5809*7887SLiane.Praza@Sun.COM 		}
5810*7887SLiane.Praza@Sun.COM 		/* if we get here, we have a constraint violation */
5811*7887SLiane.Praza@Sun.COM 		err_flag |= 0x4; /* CONSTRAINT_VIOLATED */
5812*7887SLiane.Praza@Sun.COM 		scf_values_destroy(&vals);
5813*7887SLiane.Praza@Sun.COM 		free(vstr);
5814*7887SLiane.Praza@Sun.COM 	}
5815*7887SLiane.Praza@Sun.COM 	if (err_flag != 0)
5816*7887SLiane.Praza@Sun.COM 		ret = 1;
5817*7887SLiane.Praza@Sun.COM 	/* register the errors found */
5818*7887SLiane.Praza@Sun.COM 	if (ret == 1 && errs != NULL) {
5819*7887SLiane.Praza@Sun.COM 		if ((err_flag & 0x1) == 0x1) {
5820*7887SLiane.Praza@Sun.COM 			/*
5821*7887SLiane.Praza@Sun.COM 			 * Help make the error more human-friendly.  If
5822*7887SLiane.Praza@Sun.COM 			 * pg and prop are provided, we know we're
5823*7887SLiane.Praza@Sun.COM 			 * validating repository data.  If they're not,
5824*7887SLiane.Praza@Sun.COM 			 * we're validating a potentially hypothetical
5825*7887SLiane.Praza@Sun.COM 			 * value.
5826*7887SLiane.Praza@Sun.COM 			 */
5827*7887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL)
5828*7887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_VALUE_OUT_OF_RANGE;
5829*7887SLiane.Praza@Sun.COM 			else
5830*7887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_RANGE_VIOLATION;
5831*7887SLiane.Praza@Sun.COM 			if (_add_tmpl_count_error(errs, terr_type, pg, pt,
5832*7887SLiane.Praza@Sun.COM 			    prop, v_count, 0, 0) == -1)
5833*7887SLiane.Praza@Sun.COM 				ret = -1;
5834*7887SLiane.Praza@Sun.COM 		}
5835*7887SLiane.Praza@Sun.COM 		if ((err_flag & 0x2) == 0x2) {
5836*7887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL)
5837*7887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_VALUE_OUT_OF_RANGE;
5838*7887SLiane.Praza@Sun.COM 			else
5839*7887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_RANGE_VIOLATION;
5840*7887SLiane.Praza@Sun.COM 			if (_add_tmpl_int_error(errs, terr_type, pg, pt, prop,
5841*7887SLiane.Praza@Sun.COM 			    v_int, 0, 0) == -1)
5842*7887SLiane.Praza@Sun.COM 				ret = -1;
5843*7887SLiane.Praza@Sun.COM 		}
5844*7887SLiane.Praza@Sun.COM 		if ((err_flag & 0x4) == 0x4) {
5845*7887SLiane.Praza@Sun.COM 			if (pg == NULL && prop == NULL)
5846*7887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_INVALID_VALUE;
5847*7887SLiane.Praza@Sun.COM 			else
5848*7887SLiane.Praza@Sun.COM 				terr_type = SCF_TERR_VALUE_CONSTRAINT_VIOLATED;
5849*7887SLiane.Praza@Sun.COM 			if (_add_tmpl_constraint_error(errs, terr_type, pg,
5850*7887SLiane.Praza@Sun.COM 			    pt, prop, value) == -1)
5851*7887SLiane.Praza@Sun.COM 				ret = -1;
5852*7887SLiane.Praza@Sun.COM 		}
5853*7887SLiane.Praza@Sun.COM 	}
5854*7887SLiane.Praza@Sun.COM 	return (ret);
5855*7887SLiane.Praza@Sun.COM }
5856*7887SLiane.Praza@Sun.COM 
5857*7887SLiane.Praza@Sun.COM /*
5858*7887SLiane.Praza@Sun.COM  * Returns -1 on failure.  Sets scf_error():
5859*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5860*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5861*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5862*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5863*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5864*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
5865*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5866*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5867*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5868*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5869*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5870*7887SLiane.Praza@Sun.COM  */
5871*7887SLiane.Praza@Sun.COM int
5872*7887SLiane.Praza@Sun.COM scf_tmpl_value_in_constraint(const scf_prop_tmpl_t *pt, scf_value_t *value,
5873*7887SLiane.Praza@Sun.COM     scf_tmpl_errors_t **errs)
5874*7887SLiane.Praza@Sun.COM {
5875*7887SLiane.Praza@Sun.COM 	scf_tmpl_errors_t *e = NULL;
5876*7887SLiane.Praza@Sun.COM 
5877*7887SLiane.Praza@Sun.COM 	if (errs != NULL) {
5878*7887SLiane.Praza@Sun.COM 		char *fmri;
5879*7887SLiane.Praza@Sun.COM 
5880*7887SLiane.Praza@Sun.COM 		if ((fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL)
5881*7887SLiane.Praza@Sun.COM 			return (-1);
5882*7887SLiane.Praza@Sun.COM 		*errs = _scf_create_errors(fmri, 1);
5883*7887SLiane.Praza@Sun.COM 		free(fmri);
5884*7887SLiane.Praza@Sun.COM 		if (*errs == NULL)
5885*7887SLiane.Praza@Sun.COM 			return (-1);
5886*7887SLiane.Praza@Sun.COM 		e = *errs;
5887*7887SLiane.Praza@Sun.COM 	}
5888*7887SLiane.Praza@Sun.COM 
5889*7887SLiane.Praza@Sun.COM 	return (_value_in_constraint(NULL, NULL, pt, value, e));
5890*7887SLiane.Praza@Sun.COM }
5891*7887SLiane.Praza@Sun.COM 
5892*7887SLiane.Praza@Sun.COM scf_tmpl_error_t *
5893*7887SLiane.Praza@Sun.COM scf_tmpl_next_error(scf_tmpl_errors_t *errs)
5894*7887SLiane.Praza@Sun.COM {
5895*7887SLiane.Praza@Sun.COM 	if (errs->tes_index < errs->tes_num_errs) {
5896*7887SLiane.Praza@Sun.COM 		assert(errs->tes_errs[errs->tes_index] != NULL);
5897*7887SLiane.Praza@Sun.COM 		return (errs->tes_errs[errs->tes_index++]);
5898*7887SLiane.Praza@Sun.COM 	} else {
5899*7887SLiane.Praza@Sun.COM 		return (NULL);
5900*7887SLiane.Praza@Sun.COM 	}
5901*7887SLiane.Praza@Sun.COM }
5902*7887SLiane.Praza@Sun.COM 
5903*7887SLiane.Praza@Sun.COM void
5904*7887SLiane.Praza@Sun.COM scf_tmpl_reset_errors(scf_tmpl_errors_t *errs)
5905*7887SLiane.Praza@Sun.COM {
5906*7887SLiane.Praza@Sun.COM 	errs->tes_index = 0;
5907*7887SLiane.Praza@Sun.COM }
5908*7887SLiane.Praza@Sun.COM 
5909*7887SLiane.Praza@Sun.COM int
5910*7887SLiane.Praza@Sun.COM scf_tmpl_strerror(scf_tmpl_error_t *err,  char *s, size_t n, int flag)
5911*7887SLiane.Praza@Sun.COM {
5912*7887SLiane.Praza@Sun.COM 	const char *str;
5913*7887SLiane.Praza@Sun.COM 	int i;
5914*7887SLiane.Praza@Sun.COM 	int ret = -1;
5915*7887SLiane.Praza@Sun.COM 	int nsz = 0;	/* err msg length */
5916*7887SLiane.Praza@Sun.COM 	int sz = n;	/* available buffer size */
5917*7887SLiane.Praza@Sun.COM 	char *buf = s;	/* where to append in buffer */
5918*7887SLiane.Praza@Sun.COM 	char *s0 = (flag == SCF_TMPL_STRERROR_HUMAN) ? ":\n\t" : ": ";
5919*7887SLiane.Praza@Sun.COM 	char *s1 = (flag == SCF_TMPL_STRERROR_HUMAN) ? "\n\t" : "; ";
5920*7887SLiane.Praza@Sun.COM 	char *sep = s0;
5921*7887SLiane.Praza@Sun.COM 	const char *val;
5922*7887SLiane.Praza@Sun.COM 
5923*7887SLiane.Praza@Sun.COM 	/* prefix */
5924*7887SLiane.Praza@Sun.COM 	if (err->te_errs->tes_prefix != NULL) {
5925*7887SLiane.Praza@Sun.COM 		ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN,
5926*7887SLiane.Praza@Sun.COM 		    err->te_errs->tes_prefix));
5927*7887SLiane.Praza@Sun.COM 		nsz += ret;
5928*7887SLiane.Praza@Sun.COM 		sz = (sz - ret) > 0 ? sz - ret : 0;
5929*7887SLiane.Praza@Sun.COM 		buf = (sz > 0) ? s + nsz : NULL;
5930*7887SLiane.Praza@Sun.COM 	}
5931*7887SLiane.Praza@Sun.COM 	/* error message */
5932*7887SLiane.Praza@Sun.COM 	ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN,
5933*7887SLiane.Praza@Sun.COM 	    em_desc[err->te_type].em_msg));
5934*7887SLiane.Praza@Sun.COM 	nsz += ret;
5935*7887SLiane.Praza@Sun.COM 	sz = (sz - ret) > 0 ? sz - ret : 0;
5936*7887SLiane.Praza@Sun.COM 	buf = (sz > 0) ? s + nsz : NULL;
5937*7887SLiane.Praza@Sun.COM 
5938*7887SLiane.Praza@Sun.COM 	for (i = 0; _tmpl_error_items[i].get_desc != NULL; ++i) {
5939*7887SLiane.Praza@Sun.COM 		if ((str = _tmpl_error_items[i].get_desc(err)) == NULL)
5940*7887SLiane.Praza@Sun.COM 			/* no item to print */
5941*7887SLiane.Praza@Sun.COM 			continue;
5942*7887SLiane.Praza@Sun.COM 		val = _tmpl_error_items[i].get_val(err);
5943*7887SLiane.Praza@Sun.COM 		ret = snprintf(buf, sz, "%s%s=\"%s\"", sep, str,
5944*7887SLiane.Praza@Sun.COM 		    (val == NULL) ? "" : val);
5945*7887SLiane.Praza@Sun.COM 		nsz += ret;
5946*7887SLiane.Praza@Sun.COM 		sz = (sz - ret) > 0 ? sz - ret : 0;
5947*7887SLiane.Praza@Sun.COM 		buf = (sz > 0) ? s + nsz : NULL;
5948*7887SLiane.Praza@Sun.COM 		sep = s1;
5949*7887SLiane.Praza@Sun.COM 	}
5950*7887SLiane.Praza@Sun.COM 	return (nsz);
5951*7887SLiane.Praza@Sun.COM }
5952*7887SLiane.Praza@Sun.COM 
5953*7887SLiane.Praza@Sun.COM /*
5954*7887SLiane.Praza@Sun.COM  * return 0 on success, -1 on failure.
5955*7887SLiane.Praza@Sun.COM  * set scf_error() to:
5956*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
5957*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
5958*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
5959*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
5960*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
5961*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
5962*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
5963*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
5964*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
5965*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
5966*7887SLiane.Praza@Sun.COM  */
5967*7887SLiane.Praza@Sun.COM static int
5968*7887SLiane.Praza@Sun.COM _validate_cardinality(scf_propertygroup_t *pg, scf_prop_tmpl_t *pt,
5969*7887SLiane.Praza@Sun.COM     scf_property_t *prop, scf_tmpl_errors_t *errs)
5970*7887SLiane.Praza@Sun.COM {
5971*7887SLiane.Praza@Sun.COM 	uint64_t min, max;
5972*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
5973*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
5974*7887SLiane.Praza@Sun.COM 	scf_value_t *val = NULL;
5975*7887SLiane.Praza@Sun.COM 	int count = 0;
5976*7887SLiane.Praza@Sun.COM 	int ret = -1;
5977*7887SLiane.Praza@Sun.COM 	int r;
5978*7887SLiane.Praza@Sun.COM 
5979*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_cardinality(pt, &min, &max) != 0) {
5980*7887SLiane.Praza@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND)
5981*7887SLiane.Praza@Sun.COM 			return (0);
5982*7887SLiane.Praza@Sun.COM 		else
5983*7887SLiane.Praza@Sun.COM 			return (-1);
5984*7887SLiane.Praza@Sun.COM 	}
5985*7887SLiane.Praza@Sun.COM 
5986*7887SLiane.Praza@Sun.COM 	/* Any number of values permitted.  Just return success. */
5987*7887SLiane.Praza@Sun.COM 	if (min == 0 && max == UINT64_MAX) {
5988*7887SLiane.Praza@Sun.COM 		return (0);
5989*7887SLiane.Praza@Sun.COM 	}
5990*7887SLiane.Praza@Sun.COM 
5991*7887SLiane.Praza@Sun.COM 	h = scf_property_handle(prop);
5992*7887SLiane.Praza@Sun.COM 	if (h == NULL) {
5993*7887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
5994*7887SLiane.Praza@Sun.COM 		goto cleanup;
5995*7887SLiane.Praza@Sun.COM 	}
5996*7887SLiane.Praza@Sun.COM 
5997*7887SLiane.Praza@Sun.COM 	iter = scf_iter_create(h);
5998*7887SLiane.Praza@Sun.COM 	val = scf_value_create(h);
5999*7887SLiane.Praza@Sun.COM 	if (iter == NULL || val == NULL) {
6000*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6001*7887SLiane.Praza@Sun.COM 			goto cleanup;
6002*7887SLiane.Praza@Sun.COM 		} else {
6003*7887SLiane.Praza@Sun.COM 			assert(0);
6004*7887SLiane.Praza@Sun.COM 			abort();
6005*7887SLiane.Praza@Sun.COM 		}
6006*7887SLiane.Praza@Sun.COM 	}
6007*7887SLiane.Praza@Sun.COM 
6008*7887SLiane.Praza@Sun.COM 	if (scf_iter_property_values(iter, prop) != 0) {
6009*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6010*7887SLiane.Praza@Sun.COM 			goto cleanup;
6011*7887SLiane.Praza@Sun.COM 		} else {
6012*7887SLiane.Praza@Sun.COM 			assert(0);
6013*7887SLiane.Praza@Sun.COM 			abort();
6014*7887SLiane.Praza@Sun.COM 		}
6015*7887SLiane.Praza@Sun.COM 	}
6016*7887SLiane.Praza@Sun.COM 
6017*7887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_value(iter, val)) == 1)
6018*7887SLiane.Praza@Sun.COM 		count++;
6019*7887SLiane.Praza@Sun.COM 
6020*7887SLiane.Praza@Sun.COM 	if (r < 0) {
6021*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6022*7887SLiane.Praza@Sun.COM 			goto cleanup;
6023*7887SLiane.Praza@Sun.COM 		} else {
6024*7887SLiane.Praza@Sun.COM 			assert(0);
6025*7887SLiane.Praza@Sun.COM 			abort();
6026*7887SLiane.Praza@Sun.COM 		}
6027*7887SLiane.Praza@Sun.COM 	}
6028*7887SLiane.Praza@Sun.COM 
6029*7887SLiane.Praza@Sun.COM 	if (count < min || count > max)
6030*7887SLiane.Praza@Sun.COM 		if (_add_tmpl_count_error(errs, SCF_TERR_CARDINALITY_VIOLATION,
6031*7887SLiane.Praza@Sun.COM 		    pg, pt, prop, (uint64_t)count, &min, &max) == -1)
6032*7887SLiane.Praza@Sun.COM 			goto cleanup;
6033*7887SLiane.Praza@Sun.COM 
6034*7887SLiane.Praza@Sun.COM 	ret = 0;
6035*7887SLiane.Praza@Sun.COM 
6036*7887SLiane.Praza@Sun.COM cleanup:
6037*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
6038*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
6039*7887SLiane.Praza@Sun.COM 	return (ret);
6040*7887SLiane.Praza@Sun.COM }
6041*7887SLiane.Praza@Sun.COM 
6042*7887SLiane.Praza@Sun.COM /*
6043*7887SLiane.Praza@Sun.COM  * Returns -1 on error.  Sets scf_error():
6044*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
6045*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
6046*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
6047*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
6048*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
6049*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
6050*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
6051*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
6052*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
6053*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
6054*7887SLiane.Praza@Sun.COM  */
6055*7887SLiane.Praza@Sun.COM static int
6056*7887SLiane.Praza@Sun.COM _check_property(scf_prop_tmpl_t *pt, scf_propertygroup_t *pg,
6057*7887SLiane.Praza@Sun.COM     scf_property_t *prop, scf_tmpl_errors_t *errs)
6058*7887SLiane.Praza@Sun.COM {
6059*7887SLiane.Praza@Sun.COM 	scf_type_t tmpl_type;
6060*7887SLiane.Praza@Sun.COM 	uint8_t required;
6061*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
6062*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
6063*7887SLiane.Praza@Sun.COM 	scf_value_t *val = NULL;
6064*7887SLiane.Praza@Sun.COM 	int r;
6065*7887SLiane.Praza@Sun.COM 	int ret = -1;
6066*7887SLiane.Praza@Sun.COM 
6067*7887SLiane.Praza@Sun.COM 	h = scf_pg_handle(pg);
6068*7887SLiane.Praza@Sun.COM 	if (h == NULL) {
6069*7887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
6070*7887SLiane.Praza@Sun.COM 		return (-1);
6071*7887SLiane.Praza@Sun.COM 	}
6072*7887SLiane.Praza@Sun.COM 
6073*7887SLiane.Praza@Sun.COM 	iter = scf_iter_create(h);
6074*7887SLiane.Praza@Sun.COM 	val = scf_value_create(h);
6075*7887SLiane.Praza@Sun.COM 	if (iter == NULL || val == NULL) {
6076*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6077*7887SLiane.Praza@Sun.COM 			scf_iter_destroy(iter);
6078*7887SLiane.Praza@Sun.COM 			scf_value_destroy(val);
6079*7887SLiane.Praza@Sun.COM 			return (-1);
6080*7887SLiane.Praza@Sun.COM 		} else {
6081*7887SLiane.Praza@Sun.COM 			assert(0);
6082*7887SLiane.Praza@Sun.COM 			abort();
6083*7887SLiane.Praza@Sun.COM 		}
6084*7887SLiane.Praza@Sun.COM 	}
6085*7887SLiane.Praza@Sun.COM 
6086*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_required(pt, &required) != 0)
6087*7887SLiane.Praza@Sun.COM 		goto cleanup;
6088*7887SLiane.Praza@Sun.COM 
6089*7887SLiane.Praza@Sun.COM 	/* Check type */
6090*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) {
6091*7887SLiane.Praza@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
6092*7887SLiane.Praza@Sun.COM 			goto cleanup;
6093*7887SLiane.Praza@Sun.COM 		} else if (required) {
6094*7887SLiane.Praza@Sun.COM 			/* If required, type must be specified. */
6095*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
6096*7887SLiane.Praza@Sun.COM 			goto cleanup;
6097*7887SLiane.Praza@Sun.COM 		}
6098*7887SLiane.Praza@Sun.COM 	} else if (scf_property_is_type(prop, tmpl_type) != 0) {
6099*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6100*7887SLiane.Praza@Sun.COM 			goto cleanup;
6101*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
6102*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TYPE_MISMATCH:
6103*7887SLiane.Praza@Sun.COM 			if (_add_tmpl_wrong_prop_type_error(errs, pg, pt,
6104*7887SLiane.Praza@Sun.COM 			    prop) == -1)
6105*7887SLiane.Praza@Sun.COM 				goto cleanup;
6106*7887SLiane.Praza@Sun.COM 			break;
6107*7887SLiane.Praza@Sun.COM 
6108*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
6109*7887SLiane.Praza@Sun.COM 			/*
6110*7887SLiane.Praza@Sun.COM 			 * tmpl_prop_type shouldn't have handed back
6111*7887SLiane.Praza@Sun.COM 			 * an invalid property type.
6112*7887SLiane.Praza@Sun.COM 			 */
6113*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
6114*7887SLiane.Praza@Sun.COM 		default:
6115*7887SLiane.Praza@Sun.COM 			assert(0);
6116*7887SLiane.Praza@Sun.COM 			abort();
6117*7887SLiane.Praza@Sun.COM 		}
6118*7887SLiane.Praza@Sun.COM 	}
6119*7887SLiane.Praza@Sun.COM 
6120*7887SLiane.Praza@Sun.COM 
6121*7887SLiane.Praza@Sun.COM 	/* Cardinality */
6122*7887SLiane.Praza@Sun.COM 	if (_validate_cardinality(pg, pt, prop, errs) == -1)
6123*7887SLiane.Praza@Sun.COM 		goto cleanup;
6124*7887SLiane.Praza@Sun.COM 
6125*7887SLiane.Praza@Sun.COM 	/* Value constraints */
6126*7887SLiane.Praza@Sun.COM 	/*
6127*7887SLiane.Praza@Sun.COM 	 * Iterate through each value, and confirm it is defined as
6128*7887SLiane.Praza@Sun.COM 	 * constrained.
6129*7887SLiane.Praza@Sun.COM 	 */
6130*7887SLiane.Praza@Sun.COM 	if (scf_iter_property_values(iter, prop) != 0) {
6131*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_NOT_SET &&
6132*7887SLiane.Praza@Sun.COM 		    scf_error() != SCF_ERROR_HANDLE_MISMATCH);
6133*7887SLiane.Praza@Sun.COM 		goto cleanup;
6134*7887SLiane.Praza@Sun.COM 	}
6135*7887SLiane.Praza@Sun.COM 
6136*7887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_value(iter, val)) == 1) {
6137*7887SLiane.Praza@Sun.COM 		if (_value_in_constraint(pg, prop, pt, val, errs) == -1) {
6138*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6139*7887SLiane.Praza@Sun.COM 				goto cleanup;
6140*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
6141*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_TEMPLATE_INVALID:
6142*7887SLiane.Praza@Sun.COM 				goto cleanup;
6143*7887SLiane.Praza@Sun.COM 
6144*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
6145*7887SLiane.Praza@Sun.COM 			default:
6146*7887SLiane.Praza@Sun.COM 				assert(0);
6147*7887SLiane.Praza@Sun.COM 				abort();
6148*7887SLiane.Praza@Sun.COM 			}
6149*7887SLiane.Praza@Sun.COM 		}
6150*7887SLiane.Praza@Sun.COM 	}
6151*7887SLiane.Praza@Sun.COM 
6152*7887SLiane.Praza@Sun.COM 	if (r < 0) {
6153*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6154*7887SLiane.Praza@Sun.COM 			goto cleanup;
6155*7887SLiane.Praza@Sun.COM 		} else {
6156*7887SLiane.Praza@Sun.COM 			assert(0);
6157*7887SLiane.Praza@Sun.COM 			abort();
6158*7887SLiane.Praza@Sun.COM 		}
6159*7887SLiane.Praza@Sun.COM 	}
6160*7887SLiane.Praza@Sun.COM 
6161*7887SLiane.Praza@Sun.COM 	ret = 0;
6162*7887SLiane.Praza@Sun.COM 
6163*7887SLiane.Praza@Sun.COM cleanup:
6164*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
6165*7887SLiane.Praza@Sun.COM 	scf_value_destroy(val);
6166*7887SLiane.Praza@Sun.COM 	return (ret);
6167*7887SLiane.Praza@Sun.COM }
6168*7887SLiane.Praza@Sun.COM 
6169*7887SLiane.Praza@Sun.COM /*
6170*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
6171*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
6172*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
6173*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
6174*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
6175*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
6176*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
6177*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
6178*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
6179*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
6180*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
6181*7887SLiane.Praza@Sun.COM  */
6182*7887SLiane.Praza@Sun.COM static int
6183*7887SLiane.Praza@Sun.COM _check_pg(scf_pg_tmpl_t *t, scf_propertygroup_t *pg, char *pg_name,
6184*7887SLiane.Praza@Sun.COM     char *type, scf_tmpl_errors_t *errs)
6185*7887SLiane.Praza@Sun.COM {
6186*7887SLiane.Praza@Sun.COM 	scf_prop_tmpl_t *pt = NULL;
6187*7887SLiane.Praza@Sun.COM 	char *pg_type = NULL;
6188*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
6189*7887SLiane.Praza@Sun.COM 	uint8_t pg_required;
6190*7887SLiane.Praza@Sun.COM 	scf_property_t *prop = NULL;
6191*7887SLiane.Praza@Sun.COM 	scf_handle_t *h;
6192*7887SLiane.Praza@Sun.COM 	int r;
6193*7887SLiane.Praza@Sun.COM 	char *prop_name = NULL;
6194*7887SLiane.Praza@Sun.COM 	ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
6195*7887SLiane.Praza@Sun.COM 	int ret = -1;
6196*7887SLiane.Praza@Sun.COM 
6197*7887SLiane.Praza@Sun.COM 	assert(pg_name != NULL);
6198*7887SLiane.Praza@Sun.COM 	assert(t != NULL);
6199*7887SLiane.Praza@Sun.COM 	assert(pg != NULL);
6200*7887SLiane.Praza@Sun.COM 	assert(type != NULL);
6201*7887SLiane.Praza@Sun.COM 	assert(nsize != 0);
6202*7887SLiane.Praza@Sun.COM 
6203*7887SLiane.Praza@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
6204*7887SLiane.Praza@Sun.COM 		assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED);
6205*7887SLiane.Praza@Sun.COM 		return (-1);
6206*7887SLiane.Praza@Sun.COM 	}
6207*7887SLiane.Praza@Sun.COM 	if ((pt = scf_tmpl_prop_create(h)) == NULL) {
6208*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
6209*7887SLiane.Praza@Sun.COM 		return (-1);
6210*7887SLiane.Praza@Sun.COM 	}
6211*7887SLiane.Praza@Sun.COM 
6212*7887SLiane.Praza@Sun.COM 	if ((prop = scf_property_create(h)) == NULL) {
6213*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
6214*7887SLiane.Praza@Sun.COM 		goto cleanup;
6215*7887SLiane.Praza@Sun.COM 	}
6216*7887SLiane.Praza@Sun.COM 
6217*7887SLiane.Praza@Sun.COM 	if ((iter = scf_iter_create(h)) == NULL) {
6218*7887SLiane.Praza@Sun.COM 		assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT);
6219*7887SLiane.Praza@Sun.COM 		goto cleanup;
6220*7887SLiane.Praza@Sun.COM 	}
6221*7887SLiane.Praza@Sun.COM 	if ((prop_name = malloc(nsize)) == NULL) {
6222*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
6223*7887SLiane.Praza@Sun.COM 		goto cleanup;
6224*7887SLiane.Praza@Sun.COM 	}
6225*7887SLiane.Praza@Sun.COM 
6226*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_required(t, &pg_required) != 0)
6227*7887SLiane.Praza@Sun.COM 		goto cleanup;
6228*7887SLiane.Praza@Sun.COM 
6229*7887SLiane.Praza@Sun.COM 	if (scf_tmpl_pg_type(t, &pg_type) == -1) {
6230*7887SLiane.Praza@Sun.COM 		goto cleanup;
6231*7887SLiane.Praza@Sun.COM 	} else if (pg_required != 0 &&
6232*7887SLiane.Praza@Sun.COM 	    strcmp(SCF_TMPL_WILDCARD, pg_type) == 0) {
6233*7887SLiane.Praza@Sun.COM 		/* Type must be specified for required pgs. */
6234*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
6235*7887SLiane.Praza@Sun.COM 		goto cleanup;
6236*7887SLiane.Praza@Sun.COM 	}
6237*7887SLiane.Praza@Sun.COM 
6238*7887SLiane.Praza@Sun.COM 	if (pg_type != NULL) {
6239*7887SLiane.Praza@Sun.COM 		if (strcmp(pg_type, type) != 0 &&
6240*7887SLiane.Praza@Sun.COM 		    strcmp(pg_type, SCF_TMPL_WILDCARD) != 0) {
6241*7887SLiane.Praza@Sun.COM 			if (_add_tmpl_wrong_pg_type_error(errs, t, pg) == -1)
6242*7887SLiane.Praza@Sun.COM 				goto cleanup;
6243*7887SLiane.Praza@Sun.COM 		}
6244*7887SLiane.Praza@Sun.COM 	}
6245*7887SLiane.Praza@Sun.COM 
6246*7887SLiane.Praza@Sun.COM 
6247*7887SLiane.Praza@Sun.COM 	/* Iterate through properties in the repository and check them. */
6248*7887SLiane.Praza@Sun.COM 	if (scf_iter_pg_properties(iter, pg) != 0) {
6249*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6250*7887SLiane.Praza@Sun.COM 			goto cleanup;
6251*7887SLiane.Praza@Sun.COM 		} else {
6252*7887SLiane.Praza@Sun.COM 			assert(0);
6253*7887SLiane.Praza@Sun.COM 			abort();
6254*7887SLiane.Praza@Sun.COM 		}
6255*7887SLiane.Praza@Sun.COM 	}
6256*7887SLiane.Praza@Sun.COM 
6257*7887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_property(iter, prop)) == 1) {
6258*7887SLiane.Praza@Sun.COM 		if (scf_property_get_name(prop, prop_name, nsize) == -1) {
6259*7887SLiane.Praza@Sun.COM 			assert(scf_error() != SCF_ERROR_NOT_SET);
6260*7887SLiane.Praza@Sun.COM 			goto cleanup;
6261*7887SLiane.Praza@Sun.COM 		}
6262*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_get_by_prop(t, prop_name, pt, 0) != 0) {
6263*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6264*7887SLiane.Praza@Sun.COM 				goto cleanup;
6265*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
6266*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
6267*7887SLiane.Praza@Sun.COM 				/* No template.  Continue. */
6268*7887SLiane.Praza@Sun.COM 				continue;
6269*7887SLiane.Praza@Sun.COM 
6270*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
6271*7887SLiane.Praza@Sun.COM 			default:
6272*7887SLiane.Praza@Sun.COM 				assert(0);
6273*7887SLiane.Praza@Sun.COM 				abort();
6274*7887SLiane.Praza@Sun.COM 			}
6275*7887SLiane.Praza@Sun.COM 		}
6276*7887SLiane.Praza@Sun.COM 
6277*7887SLiane.Praza@Sun.COM 		if (_check_property(pt, pg, prop, errs) != 0)
6278*7887SLiane.Praza@Sun.COM 			goto cleanup;
6279*7887SLiane.Praza@Sun.COM 	}
6280*7887SLiane.Praza@Sun.COM 
6281*7887SLiane.Praza@Sun.COM 	if (r < 0) {
6282*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6283*7887SLiane.Praza@Sun.COM 			goto cleanup;
6284*7887SLiane.Praza@Sun.COM 		} else {
6285*7887SLiane.Praza@Sun.COM 			assert(0);
6286*7887SLiane.Praza@Sun.COM 			abort();
6287*7887SLiane.Praza@Sun.COM 		}
6288*7887SLiane.Praza@Sun.COM 	}
6289*7887SLiane.Praza@Sun.COM 
6290*7887SLiane.Praza@Sun.COM 	scf_tmpl_prop_reset(pt);
6291*7887SLiane.Praza@Sun.COM 	free(prop_name);
6292*7887SLiane.Praza@Sun.COM 	prop_name = NULL;
6293*7887SLiane.Praza@Sun.COM 	/*
6294*7887SLiane.Praza@Sun.COM 	 * Confirm required properties are present.
6295*7887SLiane.Praza@Sun.COM 	 */
6296*7887SLiane.Praza@Sun.COM 	while ((r = scf_tmpl_iter_props(t, pt,
6297*7887SLiane.Praza@Sun.COM 	    SCF_PROP_TMPL_FLAG_REQUIRED)) == 0) {
6298*7887SLiane.Praza@Sun.COM 		scf_type_t prop_type;
6299*7887SLiane.Praza@Sun.COM 
6300*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_prop_name(pt, &prop_name) == -1)
6301*7887SLiane.Praza@Sun.COM 			goto cleanup;
6302*7887SLiane.Praza@Sun.COM 
6303*7887SLiane.Praza@Sun.COM 		/* required properties cannot have type wildcarded */
6304*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_prop_type(pt, &prop_type) == -1) {
6305*7887SLiane.Praza@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND)
6306*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
6307*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
6308*7887SLiane.Praza@Sun.COM 			goto cleanup;
6309*7887SLiane.Praza@Sun.COM 		}
6310*7887SLiane.Praza@Sun.COM 
6311*7887SLiane.Praza@Sun.COM 		if (scf_pg_get_property(pg, prop_name, prop) != 0) {
6312*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6313*7887SLiane.Praza@Sun.COM 				goto cleanup;
6314*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
6315*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
6316*7887SLiane.Praza@Sun.COM 				if (_add_tmpl_missing_prop_error(errs, t, pg,
6317*7887SLiane.Praza@Sun.COM 				    pt) == -1)
6318*7887SLiane.Praza@Sun.COM 					goto cleanup;
6319*7887SLiane.Praza@Sun.COM 				break;
6320*7887SLiane.Praza@Sun.COM 
6321*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
6322*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
6323*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
6324*7887SLiane.Praza@Sun.COM 				goto cleanup;
6325*7887SLiane.Praza@Sun.COM 
6326*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
6327*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
6328*7887SLiane.Praza@Sun.COM 			default:
6329*7887SLiane.Praza@Sun.COM 				assert(0);
6330*7887SLiane.Praza@Sun.COM 				abort();
6331*7887SLiane.Praza@Sun.COM 			}
6332*7887SLiane.Praza@Sun.COM 		}
6333*7887SLiane.Praza@Sun.COM 		free(prop_name);
6334*7887SLiane.Praza@Sun.COM 		prop_name = NULL;
6335*7887SLiane.Praza@Sun.COM 	}
6336*7887SLiane.Praza@Sun.COM 	if (r < 0) {
6337*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6338*7887SLiane.Praza@Sun.COM 			goto cleanup;
6339*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
6340*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
6341*7887SLiane.Praza@Sun.COM 			break;
6342*7887SLiane.Praza@Sun.COM 
6343*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_TEMPLATE_INVALID:
6344*7887SLiane.Praza@Sun.COM 			goto cleanup;
6345*7887SLiane.Praza@Sun.COM 
6346*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
6347*7887SLiane.Praza@Sun.COM 		default:
6348*7887SLiane.Praza@Sun.COM 			assert(0);
6349*7887SLiane.Praza@Sun.COM 			abort();
6350*7887SLiane.Praza@Sun.COM 		}
6351*7887SLiane.Praza@Sun.COM 	}
6352*7887SLiane.Praza@Sun.COM 
6353*7887SLiane.Praza@Sun.COM 	ret = 0;
6354*7887SLiane.Praza@Sun.COM cleanup:
6355*7887SLiane.Praza@Sun.COM 	scf_tmpl_prop_destroy(pt);
6356*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
6357*7887SLiane.Praza@Sun.COM 	scf_property_destroy(prop);
6358*7887SLiane.Praza@Sun.COM 	free(prop_name);
6359*7887SLiane.Praza@Sun.COM 	free(pg_type);
6360*7887SLiane.Praza@Sun.COM 	return (ret);
6361*7887SLiane.Praza@Sun.COM }
6362*7887SLiane.Praza@Sun.COM 
6363*7887SLiane.Praza@Sun.COM /*
6364*7887SLiane.Praza@Sun.COM  * Checks if instance fmri redefines any pgs defined in restarter or global
6365*7887SLiane.Praza@Sun.COM  * Return -1 on failure, sets scf_error() to:
6366*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
6367*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
6368*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
6369*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
6370*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
6371*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
6372*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
6373*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
6374*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
6375*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
6376*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
6377*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
6378*7887SLiane.Praza@Sun.COM  */
6379*7887SLiane.Praza@Sun.COM static int
6380*7887SLiane.Praza@Sun.COM _scf_tmpl_check_pg_redef(scf_handle_t *h, const char *fmri,
6381*7887SLiane.Praza@Sun.COM     const char *snapname, scf_tmpl_errors_t *errs)
6382*7887SLiane.Praza@Sun.COM {
6383*7887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *t = NULL;
6384*7887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *r = NULL;
6385*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
6386*7887SLiane.Praza@Sun.COM 	char *pg_name_r = NULL;
6387*7887SLiane.Praza@Sun.COM 	char *pg_type = NULL;
6388*7887SLiane.Praza@Sun.COM 	char *pg_type_r = NULL;
6389*7887SLiane.Praza@Sun.COM 	char *target = NULL;
6390*7887SLiane.Praza@Sun.COM 	int ret_val = -1;
6391*7887SLiane.Praza@Sun.COM 	int ret;
6392*7887SLiane.Praza@Sun.COM 
6393*7887SLiane.Praza@Sun.COM 	t = scf_tmpl_pg_create(h);
6394*7887SLiane.Praza@Sun.COM 	r = scf_tmpl_pg_create(h);
6395*7887SLiane.Praza@Sun.COM 	if (t == NULL || r == NULL)
6396*7887SLiane.Praza@Sun.COM 		goto cleanup;
6397*7887SLiane.Praza@Sun.COM 
6398*7887SLiane.Praza@Sun.COM 	while ((ret = scf_tmpl_iter_pgs(t, fmri, snapname, NULL,
6399*7887SLiane.Praza@Sun.COM 	    SCF_PG_TMPL_FLAG_EXACT)) == 1) {
6400*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_name(t, &pg_name) == -1) {
6401*7887SLiane.Praza@Sun.COM 			goto cleanup;
6402*7887SLiane.Praza@Sun.COM 		}
6403*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_type(t, &pg_type) == -1) {
6404*7887SLiane.Praza@Sun.COM 			goto cleanup;
6405*7887SLiane.Praza@Sun.COM 		}
6406*7887SLiane.Praza@Sun.COM 		/* look for a redefinition of a global/restarter pg_pattern */
6407*7887SLiane.Praza@Sun.COM 		while ((ret = scf_tmpl_iter_pgs(r, fmri, snapname, pg_type,
6408*7887SLiane.Praza@Sun.COM 		    0)) == 1) {
6409*7887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_name(r, &pg_name_r) == -1) {
6410*7887SLiane.Praza@Sun.COM 				goto cleanup;
6411*7887SLiane.Praza@Sun.COM 			} else if (strcmp(pg_name_r, SCF_TMPL_WILDCARD) != 0 &&
6412*7887SLiane.Praza@Sun.COM 			    strcmp(pg_name, SCF_TMPL_WILDCARD) != 0 &&
6413*7887SLiane.Praza@Sun.COM 			    strcmp(pg_name, pg_name_r) != 0) {
6414*7887SLiane.Praza@Sun.COM 				/* not a match */
6415*7887SLiane.Praza@Sun.COM 				free(pg_name_r);
6416*7887SLiane.Praza@Sun.COM 				pg_name_r = NULL;
6417*7887SLiane.Praza@Sun.COM 				continue;
6418*7887SLiane.Praza@Sun.COM 			}
6419*7887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_type(r, &pg_type_r) == -1) {
6420*7887SLiane.Praza@Sun.COM 				goto cleanup;
6421*7887SLiane.Praza@Sun.COM 			} else if (strcmp(pg_type_r, SCF_TMPL_WILDCARD) != 0 &&
6422*7887SLiane.Praza@Sun.COM 			    strcmp(pg_type, SCF_TMPL_WILDCARD) != 0 &&
6423*7887SLiane.Praza@Sun.COM 			    strcmp(pg_type, pg_type_r) != 0) {
6424*7887SLiane.Praza@Sun.COM 				/* not a match */
6425*7887SLiane.Praza@Sun.COM 				free(pg_name_r);
6426*7887SLiane.Praza@Sun.COM 				pg_name_r = NULL;
6427*7887SLiane.Praza@Sun.COM 				free(pg_type_r);
6428*7887SLiane.Praza@Sun.COM 				pg_type_r = NULL;
6429*7887SLiane.Praza@Sun.COM 				continue;
6430*7887SLiane.Praza@Sun.COM 			}
6431*7887SLiane.Praza@Sun.COM 			if (scf_tmpl_pg_target(r, &target) == -1) {
6432*7887SLiane.Praza@Sun.COM 				target = NULL;
6433*7887SLiane.Praza@Sun.COM 				goto cleanup;
6434*7887SLiane.Praza@Sun.COM 			}
6435*7887SLiane.Praza@Sun.COM 			if (strcmp(target, SCF_TM_TARGET_ALL) == 0 ||
6436*7887SLiane.Praza@Sun.COM 			    strcmp(target, SCF_TM_TARGET_DELEGATE) == 0) {
6437*7887SLiane.Praza@Sun.COM 				/* found a pg_pattern redefinition */
6438*7887SLiane.Praza@Sun.COM 				if (_add_tmpl_pg_redefine_error(errs, t,
6439*7887SLiane.Praza@Sun.COM 				    r) == -1)
6440*7887SLiane.Praza@Sun.COM 					goto cleanup;
6441*7887SLiane.Praza@Sun.COM 				free(pg_name_r);
6442*7887SLiane.Praza@Sun.COM 				pg_name_r = NULL;
6443*7887SLiane.Praza@Sun.COM 				free(target);
6444*7887SLiane.Praza@Sun.COM 				target = NULL;
6445*7887SLiane.Praza@Sun.COM 				break;
6446*7887SLiane.Praza@Sun.COM 			}
6447*7887SLiane.Praza@Sun.COM 			free(pg_name_r);
6448*7887SLiane.Praza@Sun.COM 			pg_name_r = NULL;
6449*7887SLiane.Praza@Sun.COM 			free(target);
6450*7887SLiane.Praza@Sun.COM 			target = NULL;
6451*7887SLiane.Praza@Sun.COM 		}
6452*7887SLiane.Praza@Sun.COM 		if (ret == -1)
6453*7887SLiane.Praza@Sun.COM 			goto cleanup;
6454*7887SLiane.Praza@Sun.COM 		scf_tmpl_pg_reset(r);
6455*7887SLiane.Praza@Sun.COM 
6456*7887SLiane.Praza@Sun.COM 		free(pg_name);
6457*7887SLiane.Praza@Sun.COM 		free(pg_type);
6458*7887SLiane.Praza@Sun.COM 		pg_name = NULL;
6459*7887SLiane.Praza@Sun.COM 		pg_type = NULL;
6460*7887SLiane.Praza@Sun.COM 	}
6461*7887SLiane.Praza@Sun.COM 	if (ret == -1)
6462*7887SLiane.Praza@Sun.COM 		goto cleanup;
6463*7887SLiane.Praza@Sun.COM 
6464*7887SLiane.Praza@Sun.COM 	ret_val = 0;
6465*7887SLiane.Praza@Sun.COM 
6466*7887SLiane.Praza@Sun.COM cleanup:
6467*7887SLiane.Praza@Sun.COM 	scf_tmpl_pg_destroy(t);
6468*7887SLiane.Praza@Sun.COM 	scf_tmpl_pg_destroy(r);
6469*7887SLiane.Praza@Sun.COM 	free(pg_name);
6470*7887SLiane.Praza@Sun.COM 	free(pg_type);
6471*7887SLiane.Praza@Sun.COM 	free(pg_name_r);
6472*7887SLiane.Praza@Sun.COM 	free(pg_type_r);
6473*7887SLiane.Praza@Sun.COM 	free(target);
6474*7887SLiane.Praza@Sun.COM 
6475*7887SLiane.Praza@Sun.COM 	if (ret_val == -1) {
6476*7887SLiane.Praza@Sun.COM 		if (!ismember(scf_error(), errors_server)) {
6477*7887SLiane.Praza@Sun.COM 			switch (scf_error()) {
6478*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_TYPE_MISMATCH:
6479*7887SLiane.Praza@Sun.COM 				(void) scf_set_error(
6480*7887SLiane.Praza@Sun.COM 				    SCF_ERROR_TEMPLATE_INVALID);
6481*7887SLiane.Praza@Sun.COM 				/*FALLTHROUGH*/
6482*7887SLiane.Praza@Sun.COM 
6483*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_CONSTRAINT_VIOLATED:
6484*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
6485*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
6486*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_TEMPLATE_INVALID:
6487*7887SLiane.Praza@Sun.COM 				break;
6488*7887SLiane.Praza@Sun.COM 
6489*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
6490*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
6491*7887SLiane.Praza@Sun.COM 			default:
6492*7887SLiane.Praza@Sun.COM 				assert(0);
6493*7887SLiane.Praza@Sun.COM 				abort();
6494*7887SLiane.Praza@Sun.COM 			}
6495*7887SLiane.Praza@Sun.COM 		}
6496*7887SLiane.Praza@Sun.COM 	}
6497*7887SLiane.Praza@Sun.COM 	return (ret_val);
6498*7887SLiane.Praza@Sun.COM }
6499*7887SLiane.Praza@Sun.COM 
6500*7887SLiane.Praza@Sun.COM /*
6501*7887SLiane.Praza@Sun.COM  * Returns -1 on failure, sets scf_error() to:
6502*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_BACKEND_ACCESS
6503*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_CONNECTION_BROKEN
6504*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_DELETED
6505*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_HANDLE_DESTROYED
6506*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INTERNAL
6507*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_INVALID_ARGUMENT
6508*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_MEMORY
6509*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NO_RESOURCES
6510*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_BOUND
6511*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_NOT_FOUND
6512*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_PERMISSION_DENIED
6513*7887SLiane.Praza@Sun.COM  *   SCF_ERROR_TEMPLATE_INVALID
6514*7887SLiane.Praza@Sun.COM  */
6515*7887SLiane.Praza@Sun.COM int
6516*7887SLiane.Praza@Sun.COM scf_tmpl_validate_fmri(scf_handle_t *h, const char *fmri, const char *snapshot,
6517*7887SLiane.Praza@Sun.COM     scf_tmpl_errors_t **errs, int flags)
6518*7887SLiane.Praza@Sun.COM {
6519*7887SLiane.Praza@Sun.COM 	scf_pg_tmpl_t *t = NULL;
6520*7887SLiane.Praza@Sun.COM 	scf_iter_t *iter = NULL;
6521*7887SLiane.Praza@Sun.COM 	scf_propertygroup_t *pg = NULL;
6522*7887SLiane.Praza@Sun.COM 	scf_instance_t *inst = NULL;
6523*7887SLiane.Praza@Sun.COM 	scf_snapshot_t *snap = NULL;
6524*7887SLiane.Praza@Sun.COM 	char *type = NULL;
6525*7887SLiane.Praza@Sun.COM 	char *pg_name = NULL;
6526*7887SLiane.Praza@Sun.COM 	ssize_t rsize = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
6527*7887SLiane.Praza@Sun.COM 	ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
6528*7887SLiane.Praza@Sun.COM 	int ret = -1;
6529*7887SLiane.Praza@Sun.COM 	int r;
6530*7887SLiane.Praza@Sun.COM 
6531*7887SLiane.Praza@Sun.COM 	assert(errs != NULL);
6532*7887SLiane.Praza@Sun.COM 
6533*7887SLiane.Praza@Sun.COM 	if ((*errs = _scf_create_errors(fmri, 1)) == NULL)
6534*7887SLiane.Praza@Sun.COM 		return (-1);
6535*7887SLiane.Praza@Sun.COM 
6536*7887SLiane.Praza@Sun.COM 	if ((pg = scf_pg_create(h)) == NULL ||
6537*7887SLiane.Praza@Sun.COM 	    (iter = scf_iter_create(h)) == NULL ||
6538*7887SLiane.Praza@Sun.COM 	    (inst = scf_instance_create(h)) == NULL ||
6539*7887SLiane.Praza@Sun.COM 	    (t = scf_tmpl_pg_create(h)) == NULL) {
6540*7887SLiane.Praza@Sun.COM 		/*
6541*7887SLiane.Praza@Sun.COM 		 * Sets SCF_ERROR_INVALID_ARGUMENT, SCF_ERROR_NO_MEMORY,
6542*7887SLiane.Praza@Sun.COM 		 * SCF_ERROR_NO_RESOURCES, SCF_ERROR_INTERNAL or
6543*7887SLiane.Praza@Sun.COM 		 * SCF_ERROR_HANDLE_DESTROYED.
6544*7887SLiane.Praza@Sun.COM 		 */
6545*7887SLiane.Praza@Sun.COM 		goto cleanup;
6546*7887SLiane.Praza@Sun.COM 	}
6547*7887SLiane.Praza@Sun.COM 
6548*7887SLiane.Praza@Sun.COM 	if ((type = malloc(rsize)) == NULL ||
6549*7887SLiane.Praza@Sun.COM 	    (pg_name = malloc(nsize)) == NULL) {
6550*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
6551*7887SLiane.Praza@Sun.COM 		goto cleanup;
6552*7887SLiane.Praza@Sun.COM 	}
6553*7887SLiane.Praza@Sun.COM 
6554*7887SLiane.Praza@Sun.COM 	if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, NULL,
6555*7887SLiane.Praza@Sun.COM 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
6556*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6557*7887SLiane.Praza@Sun.COM 			goto cleanup;
6558*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
6559*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_CONSTRAINT_VIOLATED:
6560*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
6561*7887SLiane.Praza@Sun.COM 			/*FALLTHROUGH*/
6562*7887SLiane.Praza@Sun.COM 
6563*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
6564*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
6565*7887SLiane.Praza@Sun.COM 			goto cleanup;
6566*7887SLiane.Praza@Sun.COM 
6567*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_HANDLE_MISMATCH:
6568*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_SET:
6569*7887SLiane.Praza@Sun.COM 		default:
6570*7887SLiane.Praza@Sun.COM 			assert(0);
6571*7887SLiane.Praza@Sun.COM 			abort();
6572*7887SLiane.Praza@Sun.COM 		}
6573*7887SLiane.Praza@Sun.COM 	}
6574*7887SLiane.Praza@Sun.COM 
6575*7887SLiane.Praza@Sun.COM 	if (snapshot == NULL || strcmp(snapshot, "running") == 0 ||
6576*7887SLiane.Praza@Sun.COM 	    (flags & SCF_TMPL_VALIDATE_FLAG_CURRENT)) {
6577*7887SLiane.Praza@Sun.COM 		if (_get_snapshot(inst, NULL, &snap) == -1)
6578*7887SLiane.Praza@Sun.COM 			goto cleanup;
6579*7887SLiane.Praza@Sun.COM 	} else {
6580*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NONE);
6581*7887SLiane.Praza@Sun.COM 		if (_get_snapshot(inst, snapshot, &snap) == -1) {
6582*7887SLiane.Praza@Sun.COM 			goto cleanup;
6583*7887SLiane.Praza@Sun.COM 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
6584*7887SLiane.Praza@Sun.COM 			goto cleanup;
6585*7887SLiane.Praza@Sun.COM 		}
6586*7887SLiane.Praza@Sun.COM 	}
6587*7887SLiane.Praza@Sun.COM 	if (_scf_tmpl_check_pg_redef(h, fmri, snapshot, *errs) != 0) {
6588*7887SLiane.Praza@Sun.COM 		goto cleanup;
6589*7887SLiane.Praza@Sun.COM 	}
6590*7887SLiane.Praza@Sun.COM 
6591*7887SLiane.Praza@Sun.COM 	/*
6592*7887SLiane.Praza@Sun.COM 	 * Check that property groups on this instance conform to the template.
6593*7887SLiane.Praza@Sun.COM 	 */
6594*7887SLiane.Praza@Sun.COM 	if (scf_iter_instance_pgs_composed(iter, inst, snap) != 0) {
6595*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6596*7887SLiane.Praza@Sun.COM 			goto cleanup;
6597*7887SLiane.Praza@Sun.COM 		} else {
6598*7887SLiane.Praza@Sun.COM 			assert(0);
6599*7887SLiane.Praza@Sun.COM 			abort();
6600*7887SLiane.Praza@Sun.COM 		}
6601*7887SLiane.Praza@Sun.COM 	}
6602*7887SLiane.Praza@Sun.COM 
6603*7887SLiane.Praza@Sun.COM 	while ((r = scf_iter_next_pg(iter, pg)) == 1) {
6604*7887SLiane.Praza@Sun.COM 		if (scf_pg_get_name(pg, pg_name, nsize) == -1) {
6605*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6606*7887SLiane.Praza@Sun.COM 				goto cleanup;
6607*7887SLiane.Praza@Sun.COM 			} else {
6608*7887SLiane.Praza@Sun.COM 				assert(0);
6609*7887SLiane.Praza@Sun.COM 				abort();
6610*7887SLiane.Praza@Sun.COM 			}
6611*7887SLiane.Praza@Sun.COM 		}
6612*7887SLiane.Praza@Sun.COM 
6613*7887SLiane.Praza@Sun.COM 		if (scf_pg_get_type(pg, type, rsize) == -1) {
6614*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6615*7887SLiane.Praza@Sun.COM 				goto cleanup;
6616*7887SLiane.Praza@Sun.COM 			} else {
6617*7887SLiane.Praza@Sun.COM 				assert(0);
6618*7887SLiane.Praza@Sun.COM 				abort();
6619*7887SLiane.Praza@Sun.COM 			}
6620*7887SLiane.Praza@Sun.COM 		}
6621*7887SLiane.Praza@Sun.COM 
6622*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_get_by_pg_name(fmri, snapshot, pg_name, type, t,
6623*7887SLiane.Praza@Sun.COM 		    0) != 0) {
6624*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6625*7887SLiane.Praza@Sun.COM 				goto cleanup;
6626*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
6627*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
6628*7887SLiane.Praza@Sun.COM 				continue;
6629*7887SLiane.Praza@Sun.COM 
6630*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
6631*7887SLiane.Praza@Sun.COM 				goto cleanup;
6632*7887SLiane.Praza@Sun.COM 
6633*7887SLiane.Praza@Sun.COM 			default:
6634*7887SLiane.Praza@Sun.COM 				assert(0);
6635*7887SLiane.Praza@Sun.COM 				abort();
6636*7887SLiane.Praza@Sun.COM 			}
6637*7887SLiane.Praza@Sun.COM 		}
6638*7887SLiane.Praza@Sun.COM 
6639*7887SLiane.Praza@Sun.COM 		if (_check_pg(t, pg, pg_name, type, *errs) != 0)
6640*7887SLiane.Praza@Sun.COM 			goto cleanup;
6641*7887SLiane.Praza@Sun.COM 	}
6642*7887SLiane.Praza@Sun.COM 	if (r < 0) {
6643*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6644*7887SLiane.Praza@Sun.COM 			goto cleanup;
6645*7887SLiane.Praza@Sun.COM 		} else {
6646*7887SLiane.Praza@Sun.COM 			assert(0);
6647*7887SLiane.Praza@Sun.COM 			abort();
6648*7887SLiane.Praza@Sun.COM 		}
6649*7887SLiane.Praza@Sun.COM 	}
6650*7887SLiane.Praza@Sun.COM 
6651*7887SLiane.Praza@Sun.COM 	scf_tmpl_pg_reset(t);
6652*7887SLiane.Praza@Sun.COM 
6653*7887SLiane.Praza@Sun.COM 	/*
6654*7887SLiane.Praza@Sun.COM 	 * Confirm required property groups are present.
6655*7887SLiane.Praza@Sun.COM 	 */
6656*7887SLiane.Praza@Sun.COM 	while ((r = scf_tmpl_iter_pgs(t, fmri, snapshot, NULL,
6657*7887SLiane.Praza@Sun.COM 	    SCF_PG_TMPL_FLAG_REQUIRED)) == 1) {
6658*7887SLiane.Praza@Sun.COM 		free(pg_name);
6659*7887SLiane.Praza@Sun.COM 		free(type);
6660*7887SLiane.Praza@Sun.COM 
6661*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_name(t, &pg_name) == -1)
6662*7887SLiane.Praza@Sun.COM 			goto cleanup;
6663*7887SLiane.Praza@Sun.COM 		if (scf_tmpl_pg_type(t, &type) == -1)
6664*7887SLiane.Praza@Sun.COM 			goto cleanup;
6665*7887SLiane.Praza@Sun.COM 		/*
6666*7887SLiane.Praza@Sun.COM 		 * required property group templates should not have
6667*7887SLiane.Praza@Sun.COM 		 * wildcarded name or type
6668*7887SLiane.Praza@Sun.COM 		 */
6669*7887SLiane.Praza@Sun.COM 		if (strcmp(pg_name, SCF_TMPL_WILDCARD) == 0 ||
6670*7887SLiane.Praza@Sun.COM 		    strcmp(type, SCF_TMPL_WILDCARD) == 0) {
6671*7887SLiane.Praza@Sun.COM 			(void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID);
6672*7887SLiane.Praza@Sun.COM 			goto cleanup;
6673*7887SLiane.Praza@Sun.COM 		}
6674*7887SLiane.Praza@Sun.COM 
6675*7887SLiane.Praza@Sun.COM 		if (_get_pg(NULL, inst, snap, pg_name, pg) != 0) {
6676*7887SLiane.Praza@Sun.COM 			if (ismember(scf_error(), errors_server)) {
6677*7887SLiane.Praza@Sun.COM 				goto cleanup;
6678*7887SLiane.Praza@Sun.COM 			} else switch (scf_error()) {
6679*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_FOUND:
6680*7887SLiane.Praza@Sun.COM 				if (_add_tmpl_missing_pg_error(*errs, t) == -1)
6681*7887SLiane.Praza@Sun.COM 					goto cleanup;
6682*7887SLiane.Praza@Sun.COM 				continue;
6683*7887SLiane.Praza@Sun.COM 
6684*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_INVALID_ARGUMENT:
6685*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_HANDLE_MISMATCH:
6686*7887SLiane.Praza@Sun.COM 			case SCF_ERROR_NOT_SET:
6687*7887SLiane.Praza@Sun.COM 			default:
6688*7887SLiane.Praza@Sun.COM 				assert(0);
6689*7887SLiane.Praza@Sun.COM 				abort();
6690*7887SLiane.Praza@Sun.COM 			}
6691*7887SLiane.Praza@Sun.COM 		}
6692*7887SLiane.Praza@Sun.COM 	}
6693*7887SLiane.Praza@Sun.COM 	if (r < 0) {
6694*7887SLiane.Praza@Sun.COM 		if (ismember(scf_error(), errors_server)) {
6695*7887SLiane.Praza@Sun.COM 			goto cleanup;
6696*7887SLiane.Praza@Sun.COM 		} else switch (scf_error()) {
6697*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_NOT_FOUND:
6698*7887SLiane.Praza@Sun.COM 			break;
6699*7887SLiane.Praza@Sun.COM 
6700*7887SLiane.Praza@Sun.COM 		case SCF_ERROR_INVALID_ARGUMENT:
6701*7887SLiane.Praza@Sun.COM 			goto cleanup;
6702*7887SLiane.Praza@Sun.COM 
6703*7887SLiane.Praza@Sun.COM 		default:
6704*7887SLiane.Praza@Sun.COM 			assert(0);
6705*7887SLiane.Praza@Sun.COM 			abort();
6706*7887SLiane.Praza@Sun.COM 		}
6707*7887SLiane.Praza@Sun.COM 	}
6708*7887SLiane.Praza@Sun.COM 
6709*7887SLiane.Praza@Sun.COM 	ret = 0;
6710*7887SLiane.Praza@Sun.COM 	if ((*errs)->tes_num_errs > 0)
6711*7887SLiane.Praza@Sun.COM 		ret = 1;
6712*7887SLiane.Praza@Sun.COM cleanup:
6713*7887SLiane.Praza@Sun.COM 	if (ret != 1) {
6714*7887SLiane.Praza@Sun.COM 		/* there are no errors to report */
6715*7887SLiane.Praza@Sun.COM 		scf_tmpl_errors_destroy(*errs);
6716*7887SLiane.Praza@Sun.COM 		*errs = NULL;
6717*7887SLiane.Praza@Sun.COM 	}
6718*7887SLiane.Praza@Sun.COM 	scf_tmpl_pg_destroy(t);
6719*7887SLiane.Praza@Sun.COM 	free(type);
6720*7887SLiane.Praza@Sun.COM 	free(pg_name);
6721*7887SLiane.Praza@Sun.COM 
6722*7887SLiane.Praza@Sun.COM 	scf_iter_destroy(iter);
6723*7887SLiane.Praza@Sun.COM 	scf_pg_destroy(pg);
6724*7887SLiane.Praza@Sun.COM 	scf_instance_destroy(inst);
6725*7887SLiane.Praza@Sun.COM 	scf_snapshot_destroy(snap);
6726*7887SLiane.Praza@Sun.COM 
6727*7887SLiane.Praza@Sun.COM 	return (ret);
6728*7887SLiane.Praza@Sun.COM }
6729*7887SLiane.Praza@Sun.COM 
6730*7887SLiane.Praza@Sun.COM void
6731*7887SLiane.Praza@Sun.COM scf_tmpl_errors_destroy(scf_tmpl_errors_t *errs)
6732*7887SLiane.Praza@Sun.COM {
6733*7887SLiane.Praza@Sun.COM 	int i;
6734*7887SLiane.Praza@Sun.COM 	scf_tmpl_error_t *e;
6735*7887SLiane.Praza@Sun.COM 
6736*7887SLiane.Praza@Sun.COM 	if (errs == NULL)
6737*7887SLiane.Praza@Sun.COM 		return;
6738*7887SLiane.Praza@Sun.COM 
6739*7887SLiane.Praza@Sun.COM 	for (i = 0; i < errs->tes_num_errs; ++i) {
6740*7887SLiane.Praza@Sun.COM 		e = errs->tes_errs[i];
6741*7887SLiane.Praza@Sun.COM 		if (errs->tes_flag != 0) {
6742*7887SLiane.Praza@Sun.COM 			free((char *)e->te_pg_name);
6743*7887SLiane.Praza@Sun.COM 			free((char *)e->te_prop_name);
6744*7887SLiane.Praza@Sun.COM 			free((char *)e->te_ev1);
6745*7887SLiane.Praza@Sun.COM 			free((char *)e->te_ev2);
6746*7887SLiane.Praza@Sun.COM 			free((char *)e->te_actual);
6747*7887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_fmri);
6748*7887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_pg_name);
6749*7887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_pg_type);
6750*7887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_prop_name);
6751*7887SLiane.Praza@Sun.COM 			free((char *)e->te_tmpl_prop_type);
6752*7887SLiane.Praza@Sun.COM 		}
6753*7887SLiane.Praza@Sun.COM 		free(e);
6754*7887SLiane.Praza@Sun.COM 	}
6755*7887SLiane.Praza@Sun.COM 	free((char *)errs->tes_fmri);
6756*7887SLiane.Praza@Sun.COM 	free((char *)errs->tes_prefix);
6757*7887SLiane.Praza@Sun.COM 	free(errs->tes_errs);
6758*7887SLiane.Praza@Sun.COM 	free(errs);
6759*7887SLiane.Praza@Sun.COM }
6760*7887SLiane.Praza@Sun.COM 
6761*7887SLiane.Praza@Sun.COM int
6762*7887SLiane.Praza@Sun.COM scf_tmpl_error_source_fmri(const scf_tmpl_error_t *err, char **fmri)
6763*7887SLiane.Praza@Sun.COM {
6764*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6765*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6766*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6767*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6768*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6769*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6770*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6771*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6772*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6773*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6774*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6775*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6776*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6777*7887SLiane.Praza@Sun.COM 		*fmri = (char *)err->te_tmpl_fmri;
6778*7887SLiane.Praza@Sun.COM 		return (0);
6779*7887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
6780*7887SLiane.Praza@Sun.COM 	default:
6781*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6782*7887SLiane.Praza@Sun.COM 	}
6783*7887SLiane.Praza@Sun.COM 	return (-1);
6784*7887SLiane.Praza@Sun.COM }
6785*7887SLiane.Praza@Sun.COM 
6786*7887SLiane.Praza@Sun.COM int
6787*7887SLiane.Praza@Sun.COM scf_tmpl_error_type(const scf_tmpl_error_t *err, scf_tmpl_error_type_t *type)
6788*7887SLiane.Praza@Sun.COM {
6789*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6790*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6791*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6792*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6793*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6794*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6795*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6796*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6797*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6798*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6799*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6800*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6801*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6802*7887SLiane.Praza@Sun.COM 		*type = err->te_type;
6803*7887SLiane.Praza@Sun.COM 		return (0);
6804*7887SLiane.Praza@Sun.COM 		/*NOTREACHED*/
6805*7887SLiane.Praza@Sun.COM 	default:
6806*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6807*7887SLiane.Praza@Sun.COM 	}
6808*7887SLiane.Praza@Sun.COM 	return (-1);
6809*7887SLiane.Praza@Sun.COM }
6810*7887SLiane.Praza@Sun.COM 
6811*7887SLiane.Praza@Sun.COM int
6812*7887SLiane.Praza@Sun.COM scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t *err, char **name, char **type)
6813*7887SLiane.Praza@Sun.COM {
6814*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6815*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6816*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6817*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6818*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6819*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6820*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6821*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6822*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6823*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6824*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6825*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6826*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6827*7887SLiane.Praza@Sun.COM 		if (err->te_tmpl_pg_name != NULL &&
6828*7887SLiane.Praza@Sun.COM 		    err->te_tmpl_pg_type != NULL) {
6829*7887SLiane.Praza@Sun.COM 			if (name != NULL)
6830*7887SLiane.Praza@Sun.COM 				*name = (char *)err->te_tmpl_pg_name;
6831*7887SLiane.Praza@Sun.COM 			if (type != NULL)
6832*7887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_pg_type;
6833*7887SLiane.Praza@Sun.COM 			return (0);
6834*7887SLiane.Praza@Sun.COM 		}
6835*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6836*7887SLiane.Praza@Sun.COM 		break;
6837*7887SLiane.Praza@Sun.COM 	default:
6838*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6839*7887SLiane.Praza@Sun.COM 	}
6840*7887SLiane.Praza@Sun.COM 	return (-1);
6841*7887SLiane.Praza@Sun.COM }
6842*7887SLiane.Praza@Sun.COM 
6843*7887SLiane.Praza@Sun.COM int
6844*7887SLiane.Praza@Sun.COM scf_tmpl_error_pg(const scf_tmpl_error_t *err, char **name, char **type)
6845*7887SLiane.Praza@Sun.COM {
6846*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6847*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6848*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6849*7887SLiane.Praza@Sun.COM 		if (err->te_pg_name != NULL &&
6850*7887SLiane.Praza@Sun.COM 		    err->te_actual != NULL) {
6851*7887SLiane.Praza@Sun.COM 			if (name != NULL)
6852*7887SLiane.Praza@Sun.COM 				*name = (char *)err->te_pg_name;
6853*7887SLiane.Praza@Sun.COM 			if (type != NULL)
6854*7887SLiane.Praza@Sun.COM 				*type = (char *)err->te_actual;
6855*7887SLiane.Praza@Sun.COM 			return (0);
6856*7887SLiane.Praza@Sun.COM 		}
6857*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6858*7887SLiane.Praza@Sun.COM 		break;
6859*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6860*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6861*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6862*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6863*7887SLiane.Praza@Sun.COM 		if (err->te_pg_name != NULL &&
6864*7887SLiane.Praza@Sun.COM 		    err->te_tmpl_pg_type != NULL) {
6865*7887SLiane.Praza@Sun.COM 			if (name != NULL)
6866*7887SLiane.Praza@Sun.COM 				*name = (char *)err->te_pg_name;
6867*7887SLiane.Praza@Sun.COM 			if (type != NULL)
6868*7887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_pg_type;
6869*7887SLiane.Praza@Sun.COM 			return (0);
6870*7887SLiane.Praza@Sun.COM 		}
6871*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
6872*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6873*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6874*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6875*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6876*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6877*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6878*7887SLiane.Praza@Sun.COM 		break;
6879*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6880*7887SLiane.Praza@Sun.COM 		if (err->te_ev1 != NULL && err->te_ev2 != NULL) {
6881*7887SLiane.Praza@Sun.COM 			if (name != NULL)
6882*7887SLiane.Praza@Sun.COM 				*name = (char *)err->te_ev1;
6883*7887SLiane.Praza@Sun.COM 			if (type != NULL)
6884*7887SLiane.Praza@Sun.COM 				*type = (char *)err->te_ev2;
6885*7887SLiane.Praza@Sun.COM 			return (0);
6886*7887SLiane.Praza@Sun.COM 		}
6887*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6888*7887SLiane.Praza@Sun.COM 		break;
6889*7887SLiane.Praza@Sun.COM 	default:
6890*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6891*7887SLiane.Praza@Sun.COM 	}
6892*7887SLiane.Praza@Sun.COM 	return (-1);
6893*7887SLiane.Praza@Sun.COM }
6894*7887SLiane.Praza@Sun.COM 
6895*7887SLiane.Praza@Sun.COM int
6896*7887SLiane.Praza@Sun.COM scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t *err, char **name, char **type)
6897*7887SLiane.Praza@Sun.COM {
6898*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6899*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6900*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6901*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6902*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6903*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6904*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6905*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6906*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6907*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6908*7887SLiane.Praza@Sun.COM 		if (err->te_tmpl_prop_name != NULL &&
6909*7887SLiane.Praza@Sun.COM 		    err->te_tmpl_prop_type != NULL) {
6910*7887SLiane.Praza@Sun.COM 			if (name != NULL)
6911*7887SLiane.Praza@Sun.COM 				*name = (char *)err->te_tmpl_prop_name;
6912*7887SLiane.Praza@Sun.COM 			if (type != NULL)
6913*7887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_prop_type;
6914*7887SLiane.Praza@Sun.COM 			return (0);
6915*7887SLiane.Praza@Sun.COM 		}
6916*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
6917*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6918*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6919*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6920*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6921*7887SLiane.Praza@Sun.COM 		break;
6922*7887SLiane.Praza@Sun.COM 	default:
6923*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6924*7887SLiane.Praza@Sun.COM 	}
6925*7887SLiane.Praza@Sun.COM 	return (-1);
6926*7887SLiane.Praza@Sun.COM }
6927*7887SLiane.Praza@Sun.COM 
6928*7887SLiane.Praza@Sun.COM int
6929*7887SLiane.Praza@Sun.COM scf_tmpl_error_prop(const scf_tmpl_error_t *err, char **name, char **type)
6930*7887SLiane.Praza@Sun.COM {
6931*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6932*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6933*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6934*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6935*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6936*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6937*7887SLiane.Praza@Sun.COM 		if (err->te_prop_name != NULL &&
6938*7887SLiane.Praza@Sun.COM 		    err->te_tmpl_prop_type != NULL) {
6939*7887SLiane.Praza@Sun.COM 			if (name != NULL)
6940*7887SLiane.Praza@Sun.COM 				*name = (char *)err->te_prop_name;
6941*7887SLiane.Praza@Sun.COM 			if (type != NULL)
6942*7887SLiane.Praza@Sun.COM 				*type = (char *)err->te_tmpl_prop_type;
6943*7887SLiane.Praza@Sun.COM 			return (0);
6944*7887SLiane.Praza@Sun.COM 		}
6945*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
6946*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6947*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6948*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6949*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6950*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6951*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6952*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6953*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6954*7887SLiane.Praza@Sun.COM 		break;
6955*7887SLiane.Praza@Sun.COM 	default:
6956*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6957*7887SLiane.Praza@Sun.COM 	}
6958*7887SLiane.Praza@Sun.COM 	return (-1);
6959*7887SLiane.Praza@Sun.COM }
6960*7887SLiane.Praza@Sun.COM 
6961*7887SLiane.Praza@Sun.COM int
6962*7887SLiane.Praza@Sun.COM scf_tmpl_error_value(const scf_tmpl_error_t *err, char **val)
6963*7887SLiane.Praza@Sun.COM {
6964*7887SLiane.Praza@Sun.COM 	assert(err != NULL);
6965*7887SLiane.Praza@Sun.COM 	switch (err->te_type) {
6966*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
6967*7887SLiane.Praza@Sun.COM 	case SCF_TERR_RANGE_VIOLATION:
6968*7887SLiane.Praza@Sun.COM 	case SCF_TERR_VALUE_OUT_OF_RANGE:
6969*7887SLiane.Praza@Sun.COM 	case SCF_TERR_INVALID_VALUE:
6970*7887SLiane.Praza@Sun.COM 		if (err->te_actual != NULL) {
6971*7887SLiane.Praza@Sun.COM 			if (val != NULL)
6972*7887SLiane.Praza@Sun.COM 				*val = (char *)err->te_actual;
6973*7887SLiane.Praza@Sun.COM 			return (0);
6974*7887SLiane.Praza@Sun.COM 		}
6975*7887SLiane.Praza@Sun.COM 		/*FALLTHROUGH*/
6976*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PG:
6977*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PG_TYPE:
6978*7887SLiane.Praza@Sun.COM 	case SCF_TERR_MISSING_PROP:
6979*7887SLiane.Praza@Sun.COM 	case SCF_TERR_WRONG_PROP_TYPE:
6980*7887SLiane.Praza@Sun.COM 	case SCF_TERR_CARDINALITY_VIOLATION:
6981*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PROP_TYPE_MISMATCH:
6982*7887SLiane.Praza@Sun.COM 	case SCF_TERR_PG_REDEFINE:
6983*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
6984*7887SLiane.Praza@Sun.COM 		break;
6985*7887SLiane.Praza@Sun.COM 	default:
6986*7887SLiane.Praza@Sun.COM 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
6987*7887SLiane.Praza@Sun.COM 	}
6988*7887SLiane.Praza@Sun.COM 	return (-1);
6989*7887SLiane.Praza@Sun.COM }
6990*7887SLiane.Praza@Sun.COM 
6991*7887SLiane.Praza@Sun.COM const char *
6992*7887SLiane.Praza@Sun.COM scf_tmpl_visibility_to_string(uint8_t vis)
6993*7887SLiane.Praza@Sun.COM {
6994*7887SLiane.Praza@Sun.COM 	if (vis == SCF_TMPL_VISIBILITY_READONLY)
6995*7887SLiane.Praza@Sun.COM 		return (SCF_TM_VISIBILITY_READONLY);
6996*7887SLiane.Praza@Sun.COM 	else if (vis == SCF_TMPL_VISIBILITY_HIDDEN)
6997*7887SLiane.Praza@Sun.COM 		return (SCF_TM_VISIBILITY_HIDDEN);
6998*7887SLiane.Praza@Sun.COM 	else if (vis == SCF_TMPL_VISIBILITY_READWRITE)
6999*7887SLiane.Praza@Sun.COM 		return (SCF_TM_VISIBILITY_READWRITE);
7000*7887SLiane.Praza@Sun.COM 	else
7001*7887SLiane.Praza@Sun.COM 		return ("unknown");
7002*7887SLiane.Praza@Sun.COM }
7003