xref: /titanic_52/usr/src/lib/libscf/common/midlevel.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include "libscf_impl.h"
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <libuutil.h>
32*7c478bd9Sstevel@tonic-gate #include <stdio.h>
33*7c478bd9Sstevel@tonic-gate #include <strings.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include "midlevel_impl.h"
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG
40*7c478bd9Sstevel@tonic-gate #define	bad_error(func, err)	{					\
41*7c478bd9Sstevel@tonic-gate 	uu_warn("%s:%d: %s failed with unexpected error %d.  Aborting.\n", \
42*7c478bd9Sstevel@tonic-gate 	    __FILE__, __LINE__, func, err);				\
43*7c478bd9Sstevel@tonic-gate 	abort();							\
44*7c478bd9Sstevel@tonic-gate }
45*7c478bd9Sstevel@tonic-gate #else
46*7c478bd9Sstevel@tonic-gate #define	bad_error(func, err)	abort()
47*7c478bd9Sstevel@tonic-gate #endif
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate  * Internal private function that creates and binds a handle.
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate static scf_handle_t *
53*7c478bd9Sstevel@tonic-gate handle_create(void)
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 	h = scf_handle_create(SCF_VERSION);
58*7c478bd9Sstevel@tonic-gate 	if (h == NULL)
59*7c478bd9Sstevel@tonic-gate 		return (NULL);
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	if (scf_handle_bind(h) == -1) {
62*7c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
63*7c478bd9Sstevel@tonic-gate 		return (NULL);
64*7c478bd9Sstevel@tonic-gate 	}
65*7c478bd9Sstevel@tonic-gate 	return (h);
66*7c478bd9Sstevel@tonic-gate }
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * Given a base service FMRI and the names of a property group and property,
70*7c478bd9Sstevel@tonic-gate  * assemble_fmri() merges them into a property FMRI.  Note that if the base
71*7c478bd9Sstevel@tonic-gate  * FMRI is NULL, assemble_fmri() gets the base FMRI from scf_myname().
72*7c478bd9Sstevel@tonic-gate  */
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate static char *
75*7c478bd9Sstevel@tonic-gate assemble_fmri(scf_handle_t *h, const char *base, const char *pg,
76*7c478bd9Sstevel@tonic-gate     const char *prop)
77*7c478bd9Sstevel@tonic-gate {
78*7c478bd9Sstevel@tonic-gate 	size_t	fmri_sz, pglen;
79*7c478bd9Sstevel@tonic-gate 	ssize_t baselen;
80*7c478bd9Sstevel@tonic-gate 	char	*fmri_buf;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 	if (prop == NULL) {
83*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
84*7c478bd9Sstevel@tonic-gate 		return (NULL);
85*7c478bd9Sstevel@tonic-gate 	}
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	if (pg == NULL)
88*7c478bd9Sstevel@tonic-gate 		pglen = strlen(SCF_PG_APP_DEFAULT);
89*7c478bd9Sstevel@tonic-gate 	else
90*7c478bd9Sstevel@tonic-gate 		pglen = strlen(pg);
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	if (base == NULL) {
93*7c478bd9Sstevel@tonic-gate 		if ((baselen = scf_myname(h, NULL, 0)) == -1)
94*7c478bd9Sstevel@tonic-gate 			return (NULL);
95*7c478bd9Sstevel@tonic-gate 	} else {
96*7c478bd9Sstevel@tonic-gate 		baselen = strlen(base);
97*7c478bd9Sstevel@tonic-gate 	}
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	fmri_sz = baselen + sizeof (SCF_FMRI_PROPERTYGRP_PREFIX) - 1 +
100*7c478bd9Sstevel@tonic-gate 	    pglen + sizeof (SCF_FMRI_PROPERTY_PREFIX) - 1 +
101*7c478bd9Sstevel@tonic-gate 	    strlen(prop) + 1;
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	if ((fmri_buf = malloc(fmri_sz)) == NULL) {
104*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
105*7c478bd9Sstevel@tonic-gate 		return (NULL);
106*7c478bd9Sstevel@tonic-gate 	}
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	if (base == NULL) {
109*7c478bd9Sstevel@tonic-gate 		if (scf_myname(h, fmri_buf, fmri_sz) == -1) {
110*7c478bd9Sstevel@tonic-gate 			free(fmri_buf);
111*7c478bd9Sstevel@tonic-gate 			return (NULL);
112*7c478bd9Sstevel@tonic-gate 		}
113*7c478bd9Sstevel@tonic-gate 	} else {
114*7c478bd9Sstevel@tonic-gate 		(void) strcpy(fmri_buf, base);
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	(void) strcat(fmri_buf, SCF_FMRI_PROPERTYGRP_PREFIX);
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	if (pg == NULL)
120*7c478bd9Sstevel@tonic-gate 		(void) strcat(fmri_buf, SCF_PG_APP_DEFAULT);
121*7c478bd9Sstevel@tonic-gate 	else
122*7c478bd9Sstevel@tonic-gate 		(void) strcat(fmri_buf, pg);
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	(void) strcat(fmri_buf, SCF_FMRI_PROPERTY_PREFIX);
125*7c478bd9Sstevel@tonic-gate 	(void) strcat(fmri_buf, prop);
126*7c478bd9Sstevel@tonic-gate 	return (fmri_buf);
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*
130*7c478bd9Sstevel@tonic-gate  * Given a property, this function allocates and fills an scf_simple_prop_t
131*7c478bd9Sstevel@tonic-gate  * with the data it contains.
132*7c478bd9Sstevel@tonic-gate  */
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate static scf_simple_prop_t *
135*7c478bd9Sstevel@tonic-gate fill_prop(scf_property_t *prop, const char *pgname, const char *propname,
136*7c478bd9Sstevel@tonic-gate     scf_handle_t *h)
137*7c478bd9Sstevel@tonic-gate {
138*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t 		*ret;
139*7c478bd9Sstevel@tonic-gate 	scf_iter_t 			*iter;
140*7c478bd9Sstevel@tonic-gate 	scf_value_t 			*val;
141*7c478bd9Sstevel@tonic-gate 	int 				iterret, i;
142*7c478bd9Sstevel@tonic-gate 	ssize_t 			valsize, numvals;
143*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val 	*vallist = NULL, *vallist_backup = NULL;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	if ((ret = malloc(sizeof (*ret))) == NULL) {
146*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
147*7c478bd9Sstevel@tonic-gate 		return (NULL);
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	ret->pr_next = NULL;
151*7c478bd9Sstevel@tonic-gate 	ret->pr_pg = NULL;
152*7c478bd9Sstevel@tonic-gate 	ret->pr_iter = 0;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	if (pgname == NULL)
155*7c478bd9Sstevel@tonic-gate 		ret->pr_pgname = strdup(SCF_PG_APP_DEFAULT);
156*7c478bd9Sstevel@tonic-gate 	else
157*7c478bd9Sstevel@tonic-gate 		ret->pr_pgname = strdup(pgname);
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	if (ret->pr_pgname == NULL) {
160*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
161*7c478bd9Sstevel@tonic-gate 		free(ret);
162*7c478bd9Sstevel@tonic-gate 		return (NULL);
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	if ((ret->pr_propname = strdup(propname)) == NULL) {
166*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
167*7c478bd9Sstevel@tonic-gate 		free(ret->pr_pgname);
168*7c478bd9Sstevel@tonic-gate 		free(ret);
169*7c478bd9Sstevel@tonic-gate 		return (NULL);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	if (scf_property_type(prop, &ret->pr_type) == -1)
173*7c478bd9Sstevel@tonic-gate 		goto error3;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	if ((iter = scf_iter_create(h)) == NULL)
176*7c478bd9Sstevel@tonic-gate 		goto error3;
177*7c478bd9Sstevel@tonic-gate 	if ((val = scf_value_create(h)) == NULL) {
178*7c478bd9Sstevel@tonic-gate 		scf_iter_destroy(iter);
179*7c478bd9Sstevel@tonic-gate 		goto error3;
180*7c478bd9Sstevel@tonic-gate 	}
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	if (scf_iter_property_values(iter, prop) == -1)
183*7c478bd9Sstevel@tonic-gate 		goto error1;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	for (numvals = 0; (iterret = scf_iter_next_value(iter, val)) == 1;
186*7c478bd9Sstevel@tonic-gate 	    numvals++) {
187*7c478bd9Sstevel@tonic-gate 		vallist_backup = vallist;
188*7c478bd9Sstevel@tonic-gate 		if ((vallist = realloc(vallist, (numvals + 1) *
189*7c478bd9Sstevel@tonic-gate 		    sizeof (*vallist))) == NULL) {
190*7c478bd9Sstevel@tonic-gate 			vallist = vallist_backup;
191*7c478bd9Sstevel@tonic-gate 			goto error1;
192*7c478bd9Sstevel@tonic-gate 		}
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 		switch (ret->pr_type) {
195*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_BOOLEAN:
196*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_boolean(val,
197*7c478bd9Sstevel@tonic-gate 			    &vallist[numvals].pv_bool) == -1)
198*7c478bd9Sstevel@tonic-gate 				goto error1;
199*7c478bd9Sstevel@tonic-gate 			break;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_COUNT:
202*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_count(val,
203*7c478bd9Sstevel@tonic-gate 			    &vallist[numvals].pv_uint) == -1)
204*7c478bd9Sstevel@tonic-gate 				goto error1;
205*7c478bd9Sstevel@tonic-gate 			break;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_INTEGER:
208*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_integer(val,
209*7c478bd9Sstevel@tonic-gate 			    &vallist[numvals].pv_int) == -1)
210*7c478bd9Sstevel@tonic-gate 				goto error1;
211*7c478bd9Sstevel@tonic-gate 			break;
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_TIME:
214*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_time(val,
215*7c478bd9Sstevel@tonic-gate 			    &vallist[numvals].pv_time.t_sec,
216*7c478bd9Sstevel@tonic-gate 			    &vallist[numvals].pv_time.t_nsec) == -1)
217*7c478bd9Sstevel@tonic-gate 				goto error1;
218*7c478bd9Sstevel@tonic-gate 			break;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_ASTRING:
221*7c478bd9Sstevel@tonic-gate 			vallist[numvals].pv_str = NULL;
222*7c478bd9Sstevel@tonic-gate 			if ((valsize = scf_value_get_astring(val, NULL, 0)) ==
223*7c478bd9Sstevel@tonic-gate 			    -1)
224*7c478bd9Sstevel@tonic-gate 				goto error1;
225*7c478bd9Sstevel@tonic-gate 			if ((vallist[numvals].pv_str = malloc(valsize+1)) ==
226*7c478bd9Sstevel@tonic-gate 			    NULL) {
227*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
228*7c478bd9Sstevel@tonic-gate 				goto error1;
229*7c478bd9Sstevel@tonic-gate 			}
230*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_astring(val,
231*7c478bd9Sstevel@tonic-gate 			    vallist[numvals].pv_str, valsize+1) == -1) {
232*7c478bd9Sstevel@tonic-gate 				free(vallist[numvals].pv_str);
233*7c478bd9Sstevel@tonic-gate 				goto error1;
234*7c478bd9Sstevel@tonic-gate 			}
235*7c478bd9Sstevel@tonic-gate 			break;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_USTRING:
238*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_HOST:
239*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_HOSTNAME:
240*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_NET_ADDR_V4:
241*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_NET_ADDR_V6:
242*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_URI:
243*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_FMRI:
244*7c478bd9Sstevel@tonic-gate 			vallist[numvals].pv_str = NULL;
245*7c478bd9Sstevel@tonic-gate 			if ((valsize = scf_value_get_ustring(val, NULL, 0)) ==
246*7c478bd9Sstevel@tonic-gate 			    -1)
247*7c478bd9Sstevel@tonic-gate 				goto error1;
248*7c478bd9Sstevel@tonic-gate 			if ((vallist[numvals].pv_str = malloc(valsize+1)) ==
249*7c478bd9Sstevel@tonic-gate 			    NULL) {
250*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
251*7c478bd9Sstevel@tonic-gate 				goto error1;
252*7c478bd9Sstevel@tonic-gate 			}
253*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_ustring(val,
254*7c478bd9Sstevel@tonic-gate 			    vallist[numvals].pv_str, valsize+1) == -1) {
255*7c478bd9Sstevel@tonic-gate 				free(vallist[numvals].pv_str);
256*7c478bd9Sstevel@tonic-gate 				goto error1;
257*7c478bd9Sstevel@tonic-gate 			}
258*7c478bd9Sstevel@tonic-gate 			break;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 		case SCF_TYPE_OPAQUE:
261*7c478bd9Sstevel@tonic-gate 			vallist[numvals].pv_opaque.o_value = NULL;
262*7c478bd9Sstevel@tonic-gate 			if ((valsize = scf_value_get_opaque(val, NULL, 0)) ==
263*7c478bd9Sstevel@tonic-gate 			    -1)
264*7c478bd9Sstevel@tonic-gate 				goto error1;
265*7c478bd9Sstevel@tonic-gate 			if ((vallist[numvals].pv_opaque.o_value =
266*7c478bd9Sstevel@tonic-gate 			    malloc(valsize)) == NULL) {
267*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
268*7c478bd9Sstevel@tonic-gate 				goto error1;
269*7c478bd9Sstevel@tonic-gate 			}
270*7c478bd9Sstevel@tonic-gate 			vallist[numvals].pv_opaque.o_size = valsize;
271*7c478bd9Sstevel@tonic-gate 			if (scf_value_get_opaque(val,
272*7c478bd9Sstevel@tonic-gate 			    vallist[numvals].pv_opaque.o_value,
273*7c478bd9Sstevel@tonic-gate 			    valsize) == -1) {
274*7c478bd9Sstevel@tonic-gate 				free(vallist[numvals].pv_opaque.o_value);
275*7c478bd9Sstevel@tonic-gate 				goto error1;
276*7c478bd9Sstevel@tonic-gate 			}
277*7c478bd9Sstevel@tonic-gate 			break;
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 		default:
280*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
281*7c478bd9Sstevel@tonic-gate 			goto error1;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 		}
284*7c478bd9Sstevel@tonic-gate 	}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	if (iterret == -1) {
287*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
288*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
289*7c478bd9Sstevel@tonic-gate 		goto error1;
290*7c478bd9Sstevel@tonic-gate 	}
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	ret->pr_vallist = vallist;
293*7c478bd9Sstevel@tonic-gate 	ret->pr_numvalues = numvals;
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
296*7c478bd9Sstevel@tonic-gate 	(void) scf_value_destroy(val);
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	return (ret);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	/*
301*7c478bd9Sstevel@tonic-gate 	 * Exit point for a successful call.  Below this line are exit points
302*7c478bd9Sstevel@tonic-gate 	 * for failures at various stages during the function.
303*7c478bd9Sstevel@tonic-gate 	 */
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate error1:
306*7c478bd9Sstevel@tonic-gate 	if (vallist == NULL)
307*7c478bd9Sstevel@tonic-gate 		goto error2;
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	switch (ret->pr_type) {
310*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_ASTRING:
311*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_USTRING:
312*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOST:
313*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOSTNAME:
314*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V4:
315*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V6:
316*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_URI:
317*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_FMRI: {
318*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < numvals; i++) {
319*7c478bd9Sstevel@tonic-gate 			free(vallist[i].pv_str);
320*7c478bd9Sstevel@tonic-gate 		}
321*7c478bd9Sstevel@tonic-gate 		break;
322*7c478bd9Sstevel@tonic-gate 	}
323*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_OPAQUE: {
324*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < numvals; i++) {
325*7c478bd9Sstevel@tonic-gate 			free(vallist[i].pv_opaque.o_value);
326*7c478bd9Sstevel@tonic-gate 		}
327*7c478bd9Sstevel@tonic-gate 		break;
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 	default:
330*7c478bd9Sstevel@tonic-gate 		break;
331*7c478bd9Sstevel@tonic-gate 	}
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	free(vallist);
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate error2:
336*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
337*7c478bd9Sstevel@tonic-gate 	(void) scf_value_destroy(val);
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate error3:
340*7c478bd9Sstevel@tonic-gate 	free(ret->pr_pgname);
341*7c478bd9Sstevel@tonic-gate 	free(ret->pr_propname);
342*7c478bd9Sstevel@tonic-gate 	free(ret);
343*7c478bd9Sstevel@tonic-gate 	return (NULL);
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate /*
347*7c478bd9Sstevel@tonic-gate  * insert_app_props iterates over a property iterator, getting all the
348*7c478bd9Sstevel@tonic-gate  * properties from a property group, and adding or overwriting them into
349*7c478bd9Sstevel@tonic-gate  * a simple_app_props_t.  This is used by scf_simple_app_props_get to provide
350*7c478bd9Sstevel@tonic-gate  * service/instance composition while filling the app_props_t.
351*7c478bd9Sstevel@tonic-gate  * insert_app_props iterates over a single property group.
352*7c478bd9Sstevel@tonic-gate  */
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate static int
355*7c478bd9Sstevel@tonic-gate insert_app_props(scf_iter_t *propiter, char *pgname, char *propname, struct
356*7c478bd9Sstevel@tonic-gate     scf_simple_pg *thispg, scf_property_t *prop, size_t namelen,
357*7c478bd9Sstevel@tonic-gate     scf_handle_t *h)
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t	*thisprop, *prevprop, *newprop;
360*7c478bd9Sstevel@tonic-gate 	uint8_t			found;
361*7c478bd9Sstevel@tonic-gate 	int			propiter_ret;
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	while ((propiter_ret = scf_iter_next_property(propiter, prop)) == 1) {
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 		if (scf_property_get_name(prop, propname, namelen) < 0) {
366*7c478bd9Sstevel@tonic-gate 			if (scf_error() == SCF_ERROR_NOT_SET)
367*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
368*7c478bd9Sstevel@tonic-gate 			return (-1);
369*7c478bd9Sstevel@tonic-gate 		}
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 		thisprop = thispg->pg_proplist;
372*7c478bd9Sstevel@tonic-gate 		prevprop = thispg->pg_proplist;
373*7c478bd9Sstevel@tonic-gate 		found = 0;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 		while ((thisprop != NULL) && (!found)) {
376*7c478bd9Sstevel@tonic-gate 			if (strcmp(thisprop->pr_propname, propname) == 0) {
377*7c478bd9Sstevel@tonic-gate 				found = 1;
378*7c478bd9Sstevel@tonic-gate 				if ((newprop = fill_prop(prop, pgname,
379*7c478bd9Sstevel@tonic-gate 				    propname, h)) == NULL)
380*7c478bd9Sstevel@tonic-gate 					return (-1);
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 				if (thisprop == thispg->pg_proplist)
383*7c478bd9Sstevel@tonic-gate 					thispg->pg_proplist = newprop;
384*7c478bd9Sstevel@tonic-gate 				else
385*7c478bd9Sstevel@tonic-gate 					prevprop->pr_next = newprop;
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 				newprop->pr_pg = thispg;
388*7c478bd9Sstevel@tonic-gate 				newprop->pr_next = thisprop->pr_next;
389*7c478bd9Sstevel@tonic-gate 				scf_simple_prop_free(thisprop);
390*7c478bd9Sstevel@tonic-gate 				thisprop = NULL;
391*7c478bd9Sstevel@tonic-gate 			} else {
392*7c478bd9Sstevel@tonic-gate 				if (thisprop != thispg->pg_proplist)
393*7c478bd9Sstevel@tonic-gate 					prevprop = prevprop->pr_next;
394*7c478bd9Sstevel@tonic-gate 				thisprop = thisprop->pr_next;
395*7c478bd9Sstevel@tonic-gate 			}
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 		if (!found) {
399*7c478bd9Sstevel@tonic-gate 			if ((newprop = fill_prop(prop, pgname, propname, h)) ==
400*7c478bd9Sstevel@tonic-gate 			    NULL)
401*7c478bd9Sstevel@tonic-gate 				return (-1);
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 			if (thispg->pg_proplist == NULL)
404*7c478bd9Sstevel@tonic-gate 				thispg->pg_proplist = newprop;
405*7c478bd9Sstevel@tonic-gate 			else
406*7c478bd9Sstevel@tonic-gate 				prevprop->pr_next = newprop;
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 			newprop->pr_pg = thispg;
409*7c478bd9Sstevel@tonic-gate 		}
410*7c478bd9Sstevel@tonic-gate 	}
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 	if (propiter_ret == -1) {
413*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
414*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
415*7c478bd9Sstevel@tonic-gate 		return (-1);
416*7c478bd9Sstevel@tonic-gate 	}
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	return (0);
419*7c478bd9Sstevel@tonic-gate }
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate /*
423*7c478bd9Sstevel@tonic-gate  * Sets up e in tx to set pname's values.  Returns 0 on success or -1 on
424*7c478bd9Sstevel@tonic-gate  * failure, with scf_error() set to
425*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_HANDLE_MISMATCH - tx & e are derived from different handles
426*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_INVALID_ARGUMENT - pname or ty are invalid
427*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_NOT_BOUND - handle is not bound
428*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_CONNECTION_BROKEN - connection was broken
429*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_NOT_SET - tx has not been started
430*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_DELETED - the pg tx was started on was deleted
431*7c478bd9Sstevel@tonic-gate  */
432*7c478bd9Sstevel@tonic-gate static int
433*7c478bd9Sstevel@tonic-gate transaction_property_set(scf_transaction_t *tx, scf_transaction_entry_t *e,
434*7c478bd9Sstevel@tonic-gate     const char *pname, scf_type_t ty)
435*7c478bd9Sstevel@tonic-gate {
436*7c478bd9Sstevel@tonic-gate 	for (;;) {
437*7c478bd9Sstevel@tonic-gate 		if (scf_transaction_property_change_type(tx, e, pname, ty) == 0)
438*7c478bd9Sstevel@tonic-gate 			return (0);
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
441*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
442*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
443*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
444*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
445*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
446*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
447*7c478bd9Sstevel@tonic-gate 		default:
448*7c478bd9Sstevel@tonic-gate 			return (-1);
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
451*7c478bd9Sstevel@tonic-gate 			break;
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 		if (scf_transaction_property_new(tx, e, pname, ty) == 0)
455*7c478bd9Sstevel@tonic-gate 			return (0);
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
458*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
459*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
460*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
461*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
462*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
463*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
464*7c478bd9Sstevel@tonic-gate 		default:
465*7c478bd9Sstevel@tonic-gate 			return (-1);
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_EXISTS:
468*7c478bd9Sstevel@tonic-gate 			break;
469*7c478bd9Sstevel@tonic-gate 		}
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate }
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate static int
474*7c478bd9Sstevel@tonic-gate get_inst_enabled(const scf_instance_t *inst, const char *pgname)
475*7c478bd9Sstevel@tonic-gate {
476*7c478bd9Sstevel@tonic-gate 	scf_propertygroup_t 	*gpg = NULL;
477*7c478bd9Sstevel@tonic-gate 	scf_property_t 		*eprop = NULL;
478*7c478bd9Sstevel@tonic-gate 	scf_value_t 		*v = NULL;
479*7c478bd9Sstevel@tonic-gate 	scf_handle_t		*h = NULL;
480*7c478bd9Sstevel@tonic-gate 	uint8_t			enabled;
481*7c478bd9Sstevel@tonic-gate 	int			ret = -1;
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	if ((h = scf_instance_handle(inst)) == NULL)
484*7c478bd9Sstevel@tonic-gate 		return (-1);
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 	if ((gpg = scf_pg_create(h)) == NULL ||
487*7c478bd9Sstevel@tonic-gate 	    (eprop = scf_property_create(h)) == NULL ||
488*7c478bd9Sstevel@tonic-gate 	    (v = scf_value_create(h)) == NULL)
489*7c478bd9Sstevel@tonic-gate 		goto out;
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, pgname, gpg) ||
492*7c478bd9Sstevel@tonic-gate 	    scf_pg_get_property(gpg, SCF_PROPERTY_ENABLED, eprop) ||
493*7c478bd9Sstevel@tonic-gate 	    scf_property_get_value(eprop, v) ||
494*7c478bd9Sstevel@tonic-gate 	    scf_value_get_boolean(v, &enabled))
495*7c478bd9Sstevel@tonic-gate 		goto out;
496*7c478bd9Sstevel@tonic-gate 	ret = enabled;
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate out:
499*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(gpg);
500*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(eprop);
501*7c478bd9Sstevel@tonic-gate 	scf_value_destroy(v);
502*7c478bd9Sstevel@tonic-gate 	return (ret);
503*7c478bd9Sstevel@tonic-gate }
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate /*
506*7c478bd9Sstevel@tonic-gate  * set_inst_enabled() is a "master" enable/disable call that takes the
507*7c478bd9Sstevel@tonic-gate  * instance and the desired state for the enabled bit in the instance's
508*7c478bd9Sstevel@tonic-gate  * named property group.  If the group doesn't exist, it's created with the
509*7c478bd9Sstevel@tonic-gate  * given flags.  Called by smf_{dis,en}able_instance().
510*7c478bd9Sstevel@tonic-gate  */
511*7c478bd9Sstevel@tonic-gate static int
512*7c478bd9Sstevel@tonic-gate set_inst_enabled(const scf_instance_t *inst, uint8_t desired,
513*7c478bd9Sstevel@tonic-gate     const char *pgname, uint32_t pgflags)
514*7c478bd9Sstevel@tonic-gate {
515*7c478bd9Sstevel@tonic-gate 	scf_transaction_t 	*tx = NULL;
516*7c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t *ent = NULL;
517*7c478bd9Sstevel@tonic-gate 	scf_propertygroup_t 	*gpg = NULL;
518*7c478bd9Sstevel@tonic-gate 	scf_property_t 		*eprop = NULL;
519*7c478bd9Sstevel@tonic-gate 	scf_value_t 		*v = NULL;
520*7c478bd9Sstevel@tonic-gate 	scf_handle_t		*h = NULL;
521*7c478bd9Sstevel@tonic-gate 	int 			ret = -1;
522*7c478bd9Sstevel@tonic-gate 	int			committed;
523*7c478bd9Sstevel@tonic-gate 	uint8_t			b;
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	if ((h = scf_instance_handle(inst)) == NULL)
526*7c478bd9Sstevel@tonic-gate 		return (-1);
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	if ((gpg = scf_pg_create(h)) == NULL ||
529*7c478bd9Sstevel@tonic-gate 	    (eprop = scf_property_create(h)) == NULL ||
530*7c478bd9Sstevel@tonic-gate 	    (v = scf_value_create(h)) == NULL ||
531*7c478bd9Sstevel@tonic-gate 	    (tx = scf_transaction_create(h)) == NULL ||
532*7c478bd9Sstevel@tonic-gate 	    (ent = scf_entry_create(h)) == NULL)
533*7c478bd9Sstevel@tonic-gate 		goto out;
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate get:
536*7c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, pgname, gpg) == -1) {
537*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
538*7c478bd9Sstevel@tonic-gate 			goto out;
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 		if (scf_instance_add_pg(inst, pgname, SCF_GROUP_FRAMEWORK,
541*7c478bd9Sstevel@tonic-gate 		    pgflags, gpg) == -1) {
542*7c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_EXISTS)
543*7c478bd9Sstevel@tonic-gate 				goto out;
544*7c478bd9Sstevel@tonic-gate 			goto get;
545*7c478bd9Sstevel@tonic-gate 		}
546*7c478bd9Sstevel@tonic-gate 	}
547*7c478bd9Sstevel@tonic-gate 	if (scf_pg_get_property(gpg, SCF_PROPERTY_ENABLED, eprop) == -1) {
548*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
549*7c478bd9Sstevel@tonic-gate 			goto out;
550*7c478bd9Sstevel@tonic-gate 		else
551*7c478bd9Sstevel@tonic-gate 			goto set;
552*7c478bd9Sstevel@tonic-gate 	}
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	/*
555*7c478bd9Sstevel@tonic-gate 	 * If it's already set the way we want, forgo the transaction.
556*7c478bd9Sstevel@tonic-gate 	 */
557*7c478bd9Sstevel@tonic-gate 	if (scf_property_get_value(eprop, v) == -1) {
558*7c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
559*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONSTRAINT_VIOLATED:
560*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
561*7c478bd9Sstevel@tonic-gate 			/* Misconfigured, so set anyway. */
562*7c478bd9Sstevel@tonic-gate 			goto set;
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 		default:
565*7c478bd9Sstevel@tonic-gate 			goto out;
566*7c478bd9Sstevel@tonic-gate 		}
567*7c478bd9Sstevel@tonic-gate 	}
568*7c478bd9Sstevel@tonic-gate 	if (scf_value_get_boolean(v, &b) == -1) {
569*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_TYPE_MISMATCH)
570*7c478bd9Sstevel@tonic-gate 			goto out;
571*7c478bd9Sstevel@tonic-gate 		goto set;
572*7c478bd9Sstevel@tonic-gate 	}
573*7c478bd9Sstevel@tonic-gate 	if (b == desired) {
574*7c478bd9Sstevel@tonic-gate 		ret = 0;
575*7c478bd9Sstevel@tonic-gate 		goto out;
576*7c478bd9Sstevel@tonic-gate 	}
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate set:
579*7c478bd9Sstevel@tonic-gate 	do {
580*7c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(tx, gpg) == -1)
581*7c478bd9Sstevel@tonic-gate 			goto out;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 		if (transaction_property_set(tx, ent, SCF_PROPERTY_ENABLED,
584*7c478bd9Sstevel@tonic-gate 		    SCF_TYPE_BOOLEAN) != 0) {
585*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
586*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
587*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
588*7c478bd9Sstevel@tonic-gate 			default:
589*7c478bd9Sstevel@tonic-gate 				goto out;
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
592*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
593*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
594*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
595*7c478bd9Sstevel@tonic-gate 				bad_error("transaction_property_set",
596*7c478bd9Sstevel@tonic-gate 				    scf_error());
597*7c478bd9Sstevel@tonic-gate 			}
598*7c478bd9Sstevel@tonic-gate 		}
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 		scf_value_set_boolean(v, desired);
601*7c478bd9Sstevel@tonic-gate 		if (scf_entry_add_value(ent, v) == -1)
602*7c478bd9Sstevel@tonic-gate 			goto out;
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 		committed = scf_transaction_commit(tx);
605*7c478bd9Sstevel@tonic-gate 		if (committed == -1)
606*7c478bd9Sstevel@tonic-gate 			goto out;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		scf_transaction_reset(tx);
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 		if (committed == 0) { /* out-of-sync */
611*7c478bd9Sstevel@tonic-gate 			if (scf_pg_update(gpg) == -1)
612*7c478bd9Sstevel@tonic-gate 				goto out;
613*7c478bd9Sstevel@tonic-gate 		}
614*7c478bd9Sstevel@tonic-gate 	} while (committed == 0);
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	ret = 0;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate out:
619*7c478bd9Sstevel@tonic-gate 	scf_value_destroy(v);
620*7c478bd9Sstevel@tonic-gate 	scf_entry_destroy(ent);
621*7c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(tx);
622*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(eprop);
623*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(gpg);
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	return (ret);
626*7c478bd9Sstevel@tonic-gate }
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate static int
629*7c478bd9Sstevel@tonic-gate delete_inst_enabled(const scf_instance_t *inst, const char *pgname)
630*7c478bd9Sstevel@tonic-gate {
631*7c478bd9Sstevel@tonic-gate 	scf_transaction_t 	*tx = NULL;
632*7c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t *ent = NULL;
633*7c478bd9Sstevel@tonic-gate 	scf_propertygroup_t 	*gpg = NULL;
634*7c478bd9Sstevel@tonic-gate 	scf_handle_t		*h = NULL;
635*7c478bd9Sstevel@tonic-gate 	int			ret = -1;
636*7c478bd9Sstevel@tonic-gate 	int			committed;
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	if ((h = scf_instance_handle(inst)) == NULL)
639*7c478bd9Sstevel@tonic-gate 		return (-1);
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 	if ((gpg = scf_pg_create(h)) == NULL ||
642*7c478bd9Sstevel@tonic-gate 	    (tx = scf_transaction_create(h)) == NULL ||
643*7c478bd9Sstevel@tonic-gate 	    (ent = scf_entry_create(h)) == NULL)
644*7c478bd9Sstevel@tonic-gate 		goto out;
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, pgname, gpg) != 0)
647*7c478bd9Sstevel@tonic-gate 		goto error;
648*7c478bd9Sstevel@tonic-gate 	do {
649*7c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(tx, gpg) == -1 ||
650*7c478bd9Sstevel@tonic-gate 		    scf_transaction_property_delete(tx, ent,
651*7c478bd9Sstevel@tonic-gate 		    SCF_PROPERTY_ENABLED) == -1 ||
652*7c478bd9Sstevel@tonic-gate 		    (committed = scf_transaction_commit(tx)) == -1)
653*7c478bd9Sstevel@tonic-gate 			goto error;
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 		scf_transaction_reset(tx);
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 		if (committed == 0 && scf_pg_update(gpg) == -1)
658*7c478bd9Sstevel@tonic-gate 			goto error;
659*7c478bd9Sstevel@tonic-gate 	} while (committed == 0);
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	ret = 0;
662*7c478bd9Sstevel@tonic-gate 	goto out;
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate error:
665*7c478bd9Sstevel@tonic-gate 	switch (scf_error()) {
666*7c478bd9Sstevel@tonic-gate 	case SCF_ERROR_DELETED:
667*7c478bd9Sstevel@tonic-gate 	case SCF_ERROR_NOT_FOUND:
668*7c478bd9Sstevel@tonic-gate 		/* success */
669*7c478bd9Sstevel@tonic-gate 		ret = 0;
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate out:
673*7c478bd9Sstevel@tonic-gate 	scf_entry_destroy(ent);
674*7c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(tx);
675*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(gpg);
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	return (ret);
678*7c478bd9Sstevel@tonic-gate }
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate /*
681*7c478bd9Sstevel@tonic-gate  * Returns 0 on success or -1 on failure.  On failure leaves scf_error() set to
682*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_HANDLE_DESTROYED - inst's handle has been destroyed
683*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_NOT_BOUND - inst's handle is not bound
684*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_CONNECTION_BROKEN - the repository connection was broken
685*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_NOT_SET - inst is not set
686*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_DELETED - inst was deleted
687*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_PERMISSION_DENIED
688*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_BACKEND_ACCESS
689*7c478bd9Sstevel@tonic-gate  *   SCF_ERROR_BACKEND_READONLY
690*7c478bd9Sstevel@tonic-gate  */
691*7c478bd9Sstevel@tonic-gate static int
692*7c478bd9Sstevel@tonic-gate set_inst_action_inst(scf_instance_t *inst, const char *action)
693*7c478bd9Sstevel@tonic-gate {
694*7c478bd9Sstevel@tonic-gate 	scf_handle_t			*h;
695*7c478bd9Sstevel@tonic-gate 	scf_transaction_t		*tx = NULL;
696*7c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t		*ent = NULL;
697*7c478bd9Sstevel@tonic-gate 	scf_propertygroup_t		*pg = NULL;
698*7c478bd9Sstevel@tonic-gate 	scf_property_t			*prop = NULL;
699*7c478bd9Sstevel@tonic-gate 	scf_value_t			*v = NULL;
700*7c478bd9Sstevel@tonic-gate 	int				trans, ret = -1;
701*7c478bd9Sstevel@tonic-gate 	int64_t				t;
702*7c478bd9Sstevel@tonic-gate 	hrtime_t			timestamp;
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	if ((h = scf_instance_handle(inst)) == NULL ||
705*7c478bd9Sstevel@tonic-gate 	    (pg = scf_pg_create(h)) == NULL ||
706*7c478bd9Sstevel@tonic-gate 	    (prop = scf_property_create(h)) == NULL ||
707*7c478bd9Sstevel@tonic-gate 	    (v = scf_value_create(h)) == NULL ||
708*7c478bd9Sstevel@tonic-gate 	    (tx = scf_transaction_create(h)) == NULL ||
709*7c478bd9Sstevel@tonic-gate 	    (ent = scf_entry_create(h)) == NULL)
710*7c478bd9Sstevel@tonic-gate 		goto out;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate get:
713*7c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, SCF_PG_RESTARTER_ACTIONS, pg) == -1) {
714*7c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
715*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
716*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
717*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
718*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
719*7c478bd9Sstevel@tonic-gate 		default:
720*7c478bd9Sstevel@tonic-gate 			goto out;
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
723*7c478bd9Sstevel@tonic-gate 			break;
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
726*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
727*7c478bd9Sstevel@tonic-gate 			bad_error("scf_instance_get_pg", scf_error());
728*7c478bd9Sstevel@tonic-gate 		}
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 		/* Try creating the restarter_actions property group. */
731*7c478bd9Sstevel@tonic-gate add:
732*7c478bd9Sstevel@tonic-gate 		if (scf_instance_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
733*7c478bd9Sstevel@tonic-gate 		    SCF_PG_RESTARTER_ACTIONS_TYPE,
734*7c478bd9Sstevel@tonic-gate 		    SCF_PG_RESTARTER_ACTIONS_FLAGS, pg) == -1) {
735*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
736*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
737*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
738*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
739*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
740*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
741*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
742*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
743*7c478bd9Sstevel@tonic-gate 			default:
744*7c478bd9Sstevel@tonic-gate 				goto out;
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_EXISTS:
747*7c478bd9Sstevel@tonic-gate 				goto get;
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
750*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
751*7c478bd9Sstevel@tonic-gate 				bad_error("scf_instance_add_pg", scf_error());
752*7c478bd9Sstevel@tonic-gate 			}
753*7c478bd9Sstevel@tonic-gate 		}
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate 	for (;;) {
757*7c478bd9Sstevel@tonic-gate 		timestamp = gethrtime();
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate 		if (scf_pg_get_property(pg, action, prop) != 0) {
760*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
761*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
762*7c478bd9Sstevel@tonic-gate 			default:
763*7c478bd9Sstevel@tonic-gate 				goto out;
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
766*7c478bd9Sstevel@tonic-gate 				goto add;
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
769*7c478bd9Sstevel@tonic-gate 				break;
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
772*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
773*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
774*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
775*7c478bd9Sstevel@tonic-gate 				bad_error("scf_pg_get_property", scf_error());
776*7c478bd9Sstevel@tonic-gate 			}
777*7c478bd9Sstevel@tonic-gate 		} else if (scf_property_get_value(prop, v) != 0) {
778*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
779*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
780*7c478bd9Sstevel@tonic-gate 			default:
781*7c478bd9Sstevel@tonic-gate 				goto out;
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
784*7c478bd9Sstevel@tonic-gate 				goto add;
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONSTRAINT_VIOLATED:
787*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
788*7c478bd9Sstevel@tonic-gate 				break;
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
791*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
792*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
793*7c478bd9Sstevel@tonic-gate 				bad_error("scf_property_get_value",
794*7c478bd9Sstevel@tonic-gate 				    scf_error());
795*7c478bd9Sstevel@tonic-gate 			}
796*7c478bd9Sstevel@tonic-gate 		} else if (scf_value_get_integer(v, &t) != 0) {
797*7c478bd9Sstevel@tonic-gate 			bad_error("scf_value_get_integer", scf_error());
798*7c478bd9Sstevel@tonic-gate 		} else if (t > timestamp) {
799*7c478bd9Sstevel@tonic-gate 			break;
800*7c478bd9Sstevel@tonic-gate 		}
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(tx, pg) == -1) {
803*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
804*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
805*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
806*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
807*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
808*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
809*7c478bd9Sstevel@tonic-gate 			default:
810*7c478bd9Sstevel@tonic-gate 				goto out;
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
813*7c478bd9Sstevel@tonic-gate 				goto add;
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
816*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
817*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_IN_USE:
818*7c478bd9Sstevel@tonic-gate 				bad_error("scf_transaction_start", scf_error());
819*7c478bd9Sstevel@tonic-gate 			}
820*7c478bd9Sstevel@tonic-gate 		}
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate 		if (transaction_property_set(tx, ent, action,
823*7c478bd9Sstevel@tonic-gate 		    SCF_TYPE_INTEGER) != 0) {
824*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
825*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
826*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
827*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
828*7c478bd9Sstevel@tonic-gate 			default:
829*7c478bd9Sstevel@tonic-gate 				goto out;
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
832*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
833*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
834*7c478bd9Sstevel@tonic-gate 				bad_error("transaction_property_set",
835*7c478bd9Sstevel@tonic-gate 				    scf_error());
836*7c478bd9Sstevel@tonic-gate 			}
837*7c478bd9Sstevel@tonic-gate 		}
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 		scf_value_set_integer(v, timestamp);
840*7c478bd9Sstevel@tonic-gate 		if (scf_entry_add_value(ent, v) == -1)
841*7c478bd9Sstevel@tonic-gate 			bad_error("scf_entry_add_value", scf_error());
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate 		trans = scf_transaction_commit(tx);
844*7c478bd9Sstevel@tonic-gate 		if (trans == 1)
845*7c478bd9Sstevel@tonic-gate 			break;
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 		if (trans != 0) {
848*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
849*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
850*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
851*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
852*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
853*7c478bd9Sstevel@tonic-gate 			default:
854*7c478bd9Sstevel@tonic-gate 				goto out;
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
857*7c478bd9Sstevel@tonic-gate 				scf_transaction_reset(tx);
858*7c478bd9Sstevel@tonic-gate 				goto add;
859*7c478bd9Sstevel@tonic-gate 
860*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
861*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
862*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
863*7c478bd9Sstevel@tonic-gate 				bad_error("scf_transaction_commit",
864*7c478bd9Sstevel@tonic-gate 				    scf_error());
865*7c478bd9Sstevel@tonic-gate 			}
866*7c478bd9Sstevel@tonic-gate 		}
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 		scf_transaction_reset(tx);
869*7c478bd9Sstevel@tonic-gate 		if (scf_pg_update(pg) != 0) {
870*7c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
871*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
872*7c478bd9Sstevel@tonic-gate 			default:
873*7c478bd9Sstevel@tonic-gate 				goto out;
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
876*7c478bd9Sstevel@tonic-gate 				goto add;
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
879*7c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
880*7c478bd9Sstevel@tonic-gate 				bad_error("scf_pg_update", scf_error());
881*7c478bd9Sstevel@tonic-gate 			}
882*7c478bd9Sstevel@tonic-gate 		}
883*7c478bd9Sstevel@tonic-gate 	}
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate 	ret = 0;
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate out:
888*7c478bd9Sstevel@tonic-gate 	scf_value_destroy(v);
889*7c478bd9Sstevel@tonic-gate 	scf_entry_destroy(ent);
890*7c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(tx);
891*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
892*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
893*7c478bd9Sstevel@tonic-gate 	return (ret);
894*7c478bd9Sstevel@tonic-gate }
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate static int
897*7c478bd9Sstevel@tonic-gate set_inst_action(const char *fmri, const char *action)
898*7c478bd9Sstevel@tonic-gate {
899*7c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
900*7c478bd9Sstevel@tonic-gate 	scf_instance_t *inst;
901*7c478bd9Sstevel@tonic-gate 	int ret = -1;
902*7c478bd9Sstevel@tonic-gate 
903*7c478bd9Sstevel@tonic-gate 	h = handle_create();
904*7c478bd9Sstevel@tonic-gate 	if (h == NULL)
905*7c478bd9Sstevel@tonic-gate 		return (-1);
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate 	inst = scf_instance_create(h);
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 	if (inst != NULL) {
910*7c478bd9Sstevel@tonic-gate 		if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL,
911*7c478bd9Sstevel@tonic-gate 		    NULL, SCF_DECODE_FMRI_EXACT) == 0)
912*7c478bd9Sstevel@tonic-gate 			ret = set_inst_action_inst(inst, action);
913*7c478bd9Sstevel@tonic-gate 		else if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
914*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 		scf_instance_destroy(inst);
917*7c478bd9Sstevel@tonic-gate 	}
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 	return (ret);
922*7c478bd9Sstevel@tonic-gate }
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate /*
926*7c478bd9Sstevel@tonic-gate  * get_inst_state() gets the state string from an instance, and returns
927*7c478bd9Sstevel@tonic-gate  * the SCF_STATE_* constant that coincides with the instance's current state.
928*7c478bd9Sstevel@tonic-gate  */
929*7c478bd9Sstevel@tonic-gate 
930*7c478bd9Sstevel@tonic-gate static int
931*7c478bd9Sstevel@tonic-gate get_inst_state(scf_instance_t *inst, scf_handle_t *h)
932*7c478bd9Sstevel@tonic-gate {
933*7c478bd9Sstevel@tonic-gate 	scf_propertygroup_t	*pg = NULL;
934*7c478bd9Sstevel@tonic-gate 	scf_property_t		*prop = NULL;
935*7c478bd9Sstevel@tonic-gate 	scf_value_t		*val = NULL;
936*7c478bd9Sstevel@tonic-gate 	char			state[MAX_SCF_STATE_STRING_SZ];
937*7c478bd9Sstevel@tonic-gate 	int			ret = -1;
938*7c478bd9Sstevel@tonic-gate 
939*7c478bd9Sstevel@tonic-gate 	if (((pg = scf_pg_create(h)) == NULL) ||
940*7c478bd9Sstevel@tonic-gate 	    ((prop = scf_property_create(h)) == NULL) ||
941*7c478bd9Sstevel@tonic-gate 	    ((val = scf_value_create(h)) == NULL))
942*7c478bd9Sstevel@tonic-gate 		goto out;
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate 	/* Pull the state property from the instance */
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, pg) == -1 ||
947*7c478bd9Sstevel@tonic-gate 	    scf_pg_get_property(pg, SCF_PROPERTY_STATE, prop) == -1 ||
948*7c478bd9Sstevel@tonic-gate 	    scf_property_get_value(prop, val) == -1) {
949*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
950*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
951*7c478bd9Sstevel@tonic-gate 		goto out;
952*7c478bd9Sstevel@tonic-gate 	}
953*7c478bd9Sstevel@tonic-gate 
954*7c478bd9Sstevel@tonic-gate 	if (scf_value_get_astring(val, state, sizeof (state)) <= 0) {
955*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_INTERNAL);
956*7c478bd9Sstevel@tonic-gate 		goto out;
957*7c478bd9Sstevel@tonic-gate 	}
958*7c478bd9Sstevel@tonic-gate 
959*7c478bd9Sstevel@tonic-gate 	if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0) {
960*7c478bd9Sstevel@tonic-gate 		ret = SCF_STATE_UNINIT;
961*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) {
962*7c478bd9Sstevel@tonic-gate 		ret = SCF_STATE_MAINT;
963*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0) {
964*7c478bd9Sstevel@tonic-gate 		ret = SCF_STATE_OFFLINE;
965*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0) {
966*7c478bd9Sstevel@tonic-gate 		ret = SCF_STATE_DISABLED;
967*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0) {
968*7c478bd9Sstevel@tonic-gate 		ret = SCF_STATE_ONLINE;
969*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0) {
970*7c478bd9Sstevel@tonic-gate 		ret = SCF_STATE_DEGRADED;
971*7c478bd9Sstevel@tonic-gate 	}
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate out:
974*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
975*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
976*7c478bd9Sstevel@tonic-gate 	(void) scf_value_destroy(val);
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 	return (ret);
979*7c478bd9Sstevel@tonic-gate }
980*7c478bd9Sstevel@tonic-gate 
981*7c478bd9Sstevel@tonic-gate /*
982*7c478bd9Sstevel@tonic-gate  * Sets an instance to be enabled or disabled after reboot, using the
983*7c478bd9Sstevel@tonic-gate  * temporary (overriding) general_ovr property group to reflect the
984*7c478bd9Sstevel@tonic-gate  * present state, if it is different.
985*7c478bd9Sstevel@tonic-gate  */
986*7c478bd9Sstevel@tonic-gate static int
987*7c478bd9Sstevel@tonic-gate set_inst_enabled_atboot(scf_instance_t *inst, uint8_t desired)
988*7c478bd9Sstevel@tonic-gate {
989*7c478bd9Sstevel@tonic-gate 	int enabled;
990*7c478bd9Sstevel@tonic-gate 	int persistent;
991*7c478bd9Sstevel@tonic-gate 	int ret = -1;
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate 	if ((persistent = get_inst_enabled(inst, SCF_PG_GENERAL)) < 0) {
994*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
995*7c478bd9Sstevel@tonic-gate 			goto out;
996*7c478bd9Sstevel@tonic-gate 		persistent = B_FALSE;
997*7c478bd9Sstevel@tonic-gate 	}
998*7c478bd9Sstevel@tonic-gate 	if ((enabled = get_inst_enabled(inst, SCF_PG_GENERAL_OVR)) < 0) {
999*7c478bd9Sstevel@tonic-gate 		enabled = persistent;
1000*7c478bd9Sstevel@tonic-gate 		if (persistent != desired) {
1001*7c478bd9Sstevel@tonic-gate 			/*
1002*7c478bd9Sstevel@tonic-gate 			 * Temporarily store the present enabled state.
1003*7c478bd9Sstevel@tonic-gate 			 */
1004*7c478bd9Sstevel@tonic-gate 			if (set_inst_enabled(inst, persistent,
1005*7c478bd9Sstevel@tonic-gate 			    SCF_PG_GENERAL_OVR, SCF_PG_GENERAL_OVR_FLAGS))
1006*7c478bd9Sstevel@tonic-gate 				goto out;
1007*7c478bd9Sstevel@tonic-gate 		}
1008*7c478bd9Sstevel@tonic-gate 	}
1009*7c478bd9Sstevel@tonic-gate 	if (persistent != desired)
1010*7c478bd9Sstevel@tonic-gate 		if (set_inst_enabled(inst, desired, SCF_PG_GENERAL,
1011*7c478bd9Sstevel@tonic-gate 		    SCF_PG_GENERAL_FLAGS))
1012*7c478bd9Sstevel@tonic-gate 			goto out;
1013*7c478bd9Sstevel@tonic-gate 	if (enabled == desired)
1014*7c478bd9Sstevel@tonic-gate 		ret = delete_inst_enabled(inst, SCF_PG_GENERAL_OVR);
1015*7c478bd9Sstevel@tonic-gate 	else
1016*7c478bd9Sstevel@tonic-gate 		ret = 0;
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate out:
1019*7c478bd9Sstevel@tonic-gate 	return (ret);
1020*7c478bd9Sstevel@tonic-gate }
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate static int
1023*7c478bd9Sstevel@tonic-gate set_inst_enabled_flags(const char *fmri, int flags, uint8_t desired)
1024*7c478bd9Sstevel@tonic-gate {
1025*7c478bd9Sstevel@tonic-gate 	int ret = -1;
1026*7c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
1027*7c478bd9Sstevel@tonic-gate 	scf_instance_t *inst;
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 	if (flags & ~(SMF_TEMPORARY | SMF_AT_NEXT_BOOT) ||
1030*7c478bd9Sstevel@tonic-gate 	    flags & SMF_TEMPORARY && flags & SMF_AT_NEXT_BOOT) {
1031*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1032*7c478bd9Sstevel@tonic-gate 		return (ret);
1033*7c478bd9Sstevel@tonic-gate 	}
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 	if ((h = handle_create()) == NULL)
1036*7c478bd9Sstevel@tonic-gate 		return (ret);
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 	if ((inst = scf_instance_create(h)) == NULL) {
1039*7c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
1040*7c478bd9Sstevel@tonic-gate 		return (ret);
1041*7c478bd9Sstevel@tonic-gate 	}
1042*7c478bd9Sstevel@tonic-gate 
1043*7c478bd9Sstevel@tonic-gate 	if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, NULL,
1044*7c478bd9Sstevel@tonic-gate 	    SCF_DECODE_FMRI_EXACT) == -1) {
1045*7c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
1046*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1047*7c478bd9Sstevel@tonic-gate 		goto out;
1048*7c478bd9Sstevel@tonic-gate 	}
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 	if (flags & SMF_AT_NEXT_BOOT) {
1051*7c478bd9Sstevel@tonic-gate 		ret = set_inst_enabled_atboot(inst, desired);
1052*7c478bd9Sstevel@tonic-gate 	} else {
1053*7c478bd9Sstevel@tonic-gate 		if (set_inst_enabled(inst, desired, flags & SMF_TEMPORARY ?
1054*7c478bd9Sstevel@tonic-gate 		    SCF_PG_GENERAL_OVR : SCF_PG_GENERAL, flags & SMF_TEMPORARY ?
1055*7c478bd9Sstevel@tonic-gate 		    SCF_PG_GENERAL_OVR_FLAGS : SCF_PG_GENERAL_FLAGS))
1056*7c478bd9Sstevel@tonic-gate 			goto out;
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 		/*
1059*7c478bd9Sstevel@tonic-gate 		 * Make the persistent value effective by deleting the
1060*7c478bd9Sstevel@tonic-gate 		 * temporary one.
1061*7c478bd9Sstevel@tonic-gate 		 */
1062*7c478bd9Sstevel@tonic-gate 		if (flags & SMF_TEMPORARY)
1063*7c478bd9Sstevel@tonic-gate 			ret = 0;
1064*7c478bd9Sstevel@tonic-gate 		else
1065*7c478bd9Sstevel@tonic-gate 			ret = delete_inst_enabled(inst, SCF_PG_GENERAL_OVR);
1066*7c478bd9Sstevel@tonic-gate 	}
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate out:
1069*7c478bd9Sstevel@tonic-gate 	scf_instance_destroy(inst);
1070*7c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
1071*7c478bd9Sstevel@tonic-gate 	return (ret);
1072*7c478bd9Sstevel@tonic-gate }
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate int
1075*7c478bd9Sstevel@tonic-gate smf_enable_instance(const char *fmri, int flags)
1076*7c478bd9Sstevel@tonic-gate {
1077*7c478bd9Sstevel@tonic-gate 	return (set_inst_enabled_flags(fmri, flags, B_TRUE));
1078*7c478bd9Sstevel@tonic-gate }
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate int
1081*7c478bd9Sstevel@tonic-gate smf_disable_instance(const char *fmri, int flags)
1082*7c478bd9Sstevel@tonic-gate {
1083*7c478bd9Sstevel@tonic-gate 	return (set_inst_enabled_flags(fmri, flags, B_FALSE));
1084*7c478bd9Sstevel@tonic-gate }
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate int
1087*7c478bd9Sstevel@tonic-gate _smf_refresh_instance_i(scf_instance_t *inst)
1088*7c478bd9Sstevel@tonic-gate {
1089*7c478bd9Sstevel@tonic-gate 	return (set_inst_action_inst(inst, SCF_PROPERTY_REFRESH));
1090*7c478bd9Sstevel@tonic-gate }
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate int
1093*7c478bd9Sstevel@tonic-gate smf_refresh_instance(const char *instance)
1094*7c478bd9Sstevel@tonic-gate {
1095*7c478bd9Sstevel@tonic-gate 	return (set_inst_action(instance, SCF_PROPERTY_REFRESH));
1096*7c478bd9Sstevel@tonic-gate }
1097*7c478bd9Sstevel@tonic-gate 
1098*7c478bd9Sstevel@tonic-gate int
1099*7c478bd9Sstevel@tonic-gate smf_restart_instance(const char *instance)
1100*7c478bd9Sstevel@tonic-gate {
1101*7c478bd9Sstevel@tonic-gate 	return (set_inst_action(instance, SCF_PROPERTY_RESTART));
1102*7c478bd9Sstevel@tonic-gate }
1103*7c478bd9Sstevel@tonic-gate 
1104*7c478bd9Sstevel@tonic-gate int
1105*7c478bd9Sstevel@tonic-gate smf_maintain_instance(const char *instance, int flags)
1106*7c478bd9Sstevel@tonic-gate {
1107*7c478bd9Sstevel@tonic-gate 	if (flags & SMF_TEMPORARY)
1108*7c478bd9Sstevel@tonic-gate 		return (set_inst_action(instance,
1109*7c478bd9Sstevel@tonic-gate 		    (flags & SMF_IMMEDIATE) ?
1110*7c478bd9Sstevel@tonic-gate 		    SCF_PROPERTY_MAINT_ON_IMMTEMP :
1111*7c478bd9Sstevel@tonic-gate 		    SCF_PROPERTY_MAINT_ON_TEMPORARY));
1112*7c478bd9Sstevel@tonic-gate 	else
1113*7c478bd9Sstevel@tonic-gate 		return (set_inst_action(instance,
1114*7c478bd9Sstevel@tonic-gate 		    (flags & SMF_IMMEDIATE) ?
1115*7c478bd9Sstevel@tonic-gate 		    SCF_PROPERTY_MAINT_ON_IMMEDIATE :
1116*7c478bd9Sstevel@tonic-gate 		    SCF_PROPERTY_MAINT_ON));
1117*7c478bd9Sstevel@tonic-gate }
1118*7c478bd9Sstevel@tonic-gate 
1119*7c478bd9Sstevel@tonic-gate int
1120*7c478bd9Sstevel@tonic-gate smf_degrade_instance(const char *instance, int flags)
1121*7c478bd9Sstevel@tonic-gate {
1122*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t		*prop;
1123*7c478bd9Sstevel@tonic-gate 	const char			*state_str;
1124*7c478bd9Sstevel@tonic-gate 
1125*7c478bd9Sstevel@tonic-gate 	if (flags & SMF_TEMPORARY)
1126*7c478bd9Sstevel@tonic-gate 		return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT));
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	if ((prop = scf_simple_prop_get(NULL, instance, SCF_PG_RESTARTER,
1129*7c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_STATE)) == NULL)
1130*7c478bd9Sstevel@tonic-gate 		return (SCF_FAILED);
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 	if ((state_str = scf_simple_prop_next_astring(prop)) == NULL) {
1133*7c478bd9Sstevel@tonic-gate 		scf_simple_prop_free(prop);
1134*7c478bd9Sstevel@tonic-gate 		return (SCF_FAILED);
1135*7c478bd9Sstevel@tonic-gate 	}
1136*7c478bd9Sstevel@tonic-gate 
1137*7c478bd9Sstevel@tonic-gate 	if (strcmp(state_str, SCF_STATE_STRING_ONLINE) != 0) {
1138*7c478bd9Sstevel@tonic-gate 		scf_simple_prop_free(prop);
1139*7c478bd9Sstevel@tonic-gate 		return (scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED));
1140*7c478bd9Sstevel@tonic-gate 	}
1141*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop);
1142*7c478bd9Sstevel@tonic-gate 
1143*7c478bd9Sstevel@tonic-gate 	return (set_inst_action(instance, (flags & SMF_IMMEDIATE) ?
1144*7c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_DEGRADE_IMMEDIATE : SCF_PROPERTY_DEGRADED));
1145*7c478bd9Sstevel@tonic-gate }
1146*7c478bd9Sstevel@tonic-gate 
1147*7c478bd9Sstevel@tonic-gate int
1148*7c478bd9Sstevel@tonic-gate smf_restore_instance(const char *instance)
1149*7c478bd9Sstevel@tonic-gate {
1150*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t		*prop;
1151*7c478bd9Sstevel@tonic-gate 	const char			*state_str;
1152*7c478bd9Sstevel@tonic-gate 	int				ret;
1153*7c478bd9Sstevel@tonic-gate 
1154*7c478bd9Sstevel@tonic-gate 	if ((prop = scf_simple_prop_get(NULL, instance, SCF_PG_RESTARTER,
1155*7c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_STATE)) == NULL)
1156*7c478bd9Sstevel@tonic-gate 		return (SCF_FAILED);
1157*7c478bd9Sstevel@tonic-gate 
1158*7c478bd9Sstevel@tonic-gate 	if ((state_str = scf_simple_prop_next_astring(prop)) == NULL) {
1159*7c478bd9Sstevel@tonic-gate 		scf_simple_prop_free(prop);
1160*7c478bd9Sstevel@tonic-gate 		return (SCF_FAILED);
1161*7c478bd9Sstevel@tonic-gate 	}
1162*7c478bd9Sstevel@tonic-gate 
1163*7c478bd9Sstevel@tonic-gate 	if (strcmp(state_str, SCF_STATE_STRING_MAINT) == 0) {
1164*7c478bd9Sstevel@tonic-gate 		ret = set_inst_action(instance, SCF_PROPERTY_MAINT_OFF);
1165*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(state_str, SCF_STATE_STRING_DEGRADED) == 0) {
1166*7c478bd9Sstevel@tonic-gate 		ret = set_inst_action(instance, SCF_PROPERTY_RESTORE);
1167*7c478bd9Sstevel@tonic-gate 	} else {
1168*7c478bd9Sstevel@tonic-gate 		ret = scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED);
1169*7c478bd9Sstevel@tonic-gate 	}
1170*7c478bd9Sstevel@tonic-gate 
1171*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop);
1172*7c478bd9Sstevel@tonic-gate 	return (ret);
1173*7c478bd9Sstevel@tonic-gate }
1174*7c478bd9Sstevel@tonic-gate 
1175*7c478bd9Sstevel@tonic-gate char *
1176*7c478bd9Sstevel@tonic-gate smf_get_state(const char *instance)
1177*7c478bd9Sstevel@tonic-gate {
1178*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t		*prop;
1179*7c478bd9Sstevel@tonic-gate 	const char			*state_str;
1180*7c478bd9Sstevel@tonic-gate 	char				*ret;
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate 	if ((prop = scf_simple_prop_get(NULL, instance, SCF_PG_RESTARTER,
1183*7c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_STATE)) == NULL)
1184*7c478bd9Sstevel@tonic-gate 		return (NULL);
1185*7c478bd9Sstevel@tonic-gate 
1186*7c478bd9Sstevel@tonic-gate 	if ((state_str = scf_simple_prop_next_astring(prop)) == NULL) {
1187*7c478bd9Sstevel@tonic-gate 		scf_simple_prop_free(prop);
1188*7c478bd9Sstevel@tonic-gate 		return (NULL);
1189*7c478bd9Sstevel@tonic-gate 	}
1190*7c478bd9Sstevel@tonic-gate 
1191*7c478bd9Sstevel@tonic-gate 	if ((ret = strdup(state_str)) == NULL)
1192*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1193*7c478bd9Sstevel@tonic-gate 
1194*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop);
1195*7c478bd9Sstevel@tonic-gate 	return (ret);
1196*7c478bd9Sstevel@tonic-gate }
1197*7c478bd9Sstevel@tonic-gate 
1198*7c478bd9Sstevel@tonic-gate int
1199*7c478bd9Sstevel@tonic-gate scf_simple_walk_instances(uint_t state_flags, void *private,
1200*7c478bd9Sstevel@tonic-gate     int (*inst_callback)(scf_handle_t *, scf_instance_t *, void *))
1201*7c478bd9Sstevel@tonic-gate {
1202*7c478bd9Sstevel@tonic-gate 	scf_scope_t 		*scope = NULL;
1203*7c478bd9Sstevel@tonic-gate 	scf_service_t		*svc = NULL;
1204*7c478bd9Sstevel@tonic-gate 	scf_instance_t		*inst = NULL;
1205*7c478bd9Sstevel@tonic-gate 	scf_iter_t		*svc_iter = NULL, *inst_iter = NULL;
1206*7c478bd9Sstevel@tonic-gate 	scf_handle_t		*h = NULL;
1207*7c478bd9Sstevel@tonic-gate 	int			ret = SCF_FAILED;
1208*7c478bd9Sstevel@tonic-gate 	int			svc_iter_ret, inst_iter_ret;
1209*7c478bd9Sstevel@tonic-gate 	int			inst_state;
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate 	if ((h = handle_create()) == NULL)
1212*7c478bd9Sstevel@tonic-gate 		return (ret);
1213*7c478bd9Sstevel@tonic-gate 
1214*7c478bd9Sstevel@tonic-gate 	if (((scope = scf_scope_create(h)) == NULL) ||
1215*7c478bd9Sstevel@tonic-gate 	    ((svc = scf_service_create(h)) == NULL) ||
1216*7c478bd9Sstevel@tonic-gate 	    ((inst = scf_instance_create(h)) == NULL) ||
1217*7c478bd9Sstevel@tonic-gate 	    ((svc_iter = scf_iter_create(h)) == NULL) ||
1218*7c478bd9Sstevel@tonic-gate 	    ((inst_iter = scf_iter_create(h)) == NULL))
1219*7c478bd9Sstevel@tonic-gate 		goto out;
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate 	/*
1222*7c478bd9Sstevel@tonic-gate 	 * Get the local scope, and set up nested iteration through every
1223*7c478bd9Sstevel@tonic-gate 	 * local service, and every instance of every service.
1224*7c478bd9Sstevel@tonic-gate 	 */
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate 	if ((scf_handle_get_local_scope(h, scope) != SCF_SUCCESS) ||
1227*7c478bd9Sstevel@tonic-gate 	    (scf_iter_scope_services(svc_iter, scope) != SCF_SUCCESS))
1228*7c478bd9Sstevel@tonic-gate 		goto out;
1229*7c478bd9Sstevel@tonic-gate 
1230*7c478bd9Sstevel@tonic-gate 	while ((svc_iter_ret = scf_iter_next_service(svc_iter, svc)) > 0) {
1231*7c478bd9Sstevel@tonic-gate 
1232*7c478bd9Sstevel@tonic-gate 		if ((scf_iter_service_instances(inst_iter, svc)) !=
1233*7c478bd9Sstevel@tonic-gate 		    SCF_SUCCESS)
1234*7c478bd9Sstevel@tonic-gate 			goto out;
1235*7c478bd9Sstevel@tonic-gate 
1236*7c478bd9Sstevel@tonic-gate 		while ((inst_iter_ret =
1237*7c478bd9Sstevel@tonic-gate 		    scf_iter_next_instance(inst_iter, inst)) > 0) {
1238*7c478bd9Sstevel@tonic-gate 			/*
1239*7c478bd9Sstevel@tonic-gate 			 * If get_inst_state fails from an internal error,
1240*7c478bd9Sstevel@tonic-gate 			 * IE, being unable to get the property group or
1241*7c478bd9Sstevel@tonic-gate 			 * property containing the state of the instance,
1242*7c478bd9Sstevel@tonic-gate 			 * we continue instead of failing, as this might just
1243*7c478bd9Sstevel@tonic-gate 			 * be an improperly configured instance.
1244*7c478bd9Sstevel@tonic-gate 			 */
1245*7c478bd9Sstevel@tonic-gate 			if ((inst_state = get_inst_state(inst, h)) == -1) {
1246*7c478bd9Sstevel@tonic-gate 				if (scf_error() == SCF_ERROR_INTERNAL) {
1247*7c478bd9Sstevel@tonic-gate 					continue;
1248*7c478bd9Sstevel@tonic-gate 				} else {
1249*7c478bd9Sstevel@tonic-gate 					goto out;
1250*7c478bd9Sstevel@tonic-gate 				}
1251*7c478bd9Sstevel@tonic-gate 			}
1252*7c478bd9Sstevel@tonic-gate 
1253*7c478bd9Sstevel@tonic-gate 			if ((uint_t)inst_state & state_flags) {
1254*7c478bd9Sstevel@tonic-gate 				if (inst_callback(h, inst, private) !=
1255*7c478bd9Sstevel@tonic-gate 				    SCF_SUCCESS) {
1256*7c478bd9Sstevel@tonic-gate 					(void) scf_set_error(
1257*7c478bd9Sstevel@tonic-gate 					    SCF_ERROR_CALLBACK_FAILED);
1258*7c478bd9Sstevel@tonic-gate 					goto out;
1259*7c478bd9Sstevel@tonic-gate 				}
1260*7c478bd9Sstevel@tonic-gate 			}
1261*7c478bd9Sstevel@tonic-gate 		}
1262*7c478bd9Sstevel@tonic-gate 
1263*7c478bd9Sstevel@tonic-gate 		if (inst_iter_ret == -1)
1264*7c478bd9Sstevel@tonic-gate 			goto out;
1265*7c478bd9Sstevel@tonic-gate 		scf_iter_reset(inst_iter);
1266*7c478bd9Sstevel@tonic-gate 	}
1267*7c478bd9Sstevel@tonic-gate 
1268*7c478bd9Sstevel@tonic-gate 	if (svc_iter_ret != -1)
1269*7c478bd9Sstevel@tonic-gate 		ret = SCF_SUCCESS;
1270*7c478bd9Sstevel@tonic-gate 
1271*7c478bd9Sstevel@tonic-gate out:
1272*7c478bd9Sstevel@tonic-gate 	scf_scope_destroy(scope);
1273*7c478bd9Sstevel@tonic-gate 	scf_service_destroy(svc);
1274*7c478bd9Sstevel@tonic-gate 	scf_instance_destroy(inst);
1275*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(svc_iter);
1276*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(inst_iter);
1277*7c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate 	return (ret);
1280*7c478bd9Sstevel@tonic-gate }
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 
1283*7c478bd9Sstevel@tonic-gate scf_simple_prop_t *
1284*7c478bd9Sstevel@tonic-gate scf_simple_prop_get(scf_handle_t *hin, const char *instance, const char *pgname,
1285*7c478bd9Sstevel@tonic-gate 			const char *propname)
1286*7c478bd9Sstevel@tonic-gate {
1287*7c478bd9Sstevel@tonic-gate 	char 			*fmri_buf, *svcfmri = NULL;
1288*7c478bd9Sstevel@tonic-gate 	ssize_t 		fmri_sz;
1289*7c478bd9Sstevel@tonic-gate 	scf_property_t 		*prop = NULL;
1290*7c478bd9Sstevel@tonic-gate 	scf_service_t 		*svc = NULL;
1291*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t 	*ret;
1292*7c478bd9Sstevel@tonic-gate 	scf_handle_t		*h = NULL;
1293*7c478bd9Sstevel@tonic-gate 	boolean_t		local_h = B_TRUE;
1294*7c478bd9Sstevel@tonic-gate 
1295*7c478bd9Sstevel@tonic-gate 	/* If the user passed in a handle, use it. */
1296*7c478bd9Sstevel@tonic-gate 	if (hin != NULL) {
1297*7c478bd9Sstevel@tonic-gate 		h = hin;
1298*7c478bd9Sstevel@tonic-gate 		local_h = B_FALSE;
1299*7c478bd9Sstevel@tonic-gate 	}
1300*7c478bd9Sstevel@tonic-gate 
1301*7c478bd9Sstevel@tonic-gate 	if (local_h && ((h = handle_create()) == NULL))
1302*7c478bd9Sstevel@tonic-gate 		return (NULL);
1303*7c478bd9Sstevel@tonic-gate 
1304*7c478bd9Sstevel@tonic-gate 	if ((fmri_buf = assemble_fmri(h, instance, pgname, propname)) == NULL) {
1305*7c478bd9Sstevel@tonic-gate 		if (local_h)
1306*7c478bd9Sstevel@tonic-gate 			scf_handle_destroy(h);
1307*7c478bd9Sstevel@tonic-gate 		return (NULL);
1308*7c478bd9Sstevel@tonic-gate 	}
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate 	if ((svc = scf_service_create(h)) == NULL ||
1311*7c478bd9Sstevel@tonic-gate 	    (prop = scf_property_create(h)) == NULL)
1312*7c478bd9Sstevel@tonic-gate 		goto error1;
1313*7c478bd9Sstevel@tonic-gate 	if (scf_handle_decode_fmri(h, fmri_buf, NULL, NULL, NULL, NULL, prop,
1314*7c478bd9Sstevel@tonic-gate 	    SCF_DECODE_FMRI_REQUIRE_INSTANCE) == -1) {
1315*7c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
1316*7c478bd9Sstevel@tonic-gate 		/*
1317*7c478bd9Sstevel@tonic-gate 		 * If the property isn't found in the instance, we grab the
1318*7c478bd9Sstevel@tonic-gate 		 * underlying service, create an FMRI out of it, and then
1319*7c478bd9Sstevel@tonic-gate 		 * query the datastore again at the service level for the
1320*7c478bd9Sstevel@tonic-gate 		 * property.
1321*7c478bd9Sstevel@tonic-gate 		 */
1322*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
1323*7c478bd9Sstevel@tonic-gate 			if (scf_handle_decode_fmri(h, fmri_buf, NULL, svc,
1324*7c478bd9Sstevel@tonic-gate 			    NULL, NULL, NULL, SCF_DECODE_FMRI_TRUNCATE) == -1)
1325*7c478bd9Sstevel@tonic-gate 				goto error1;
1326*7c478bd9Sstevel@tonic-gate 			if ((fmri_sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH)) ==
1327*7c478bd9Sstevel@tonic-gate 			    -1) {
1328*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
1329*7c478bd9Sstevel@tonic-gate 				goto error1;
1330*7c478bd9Sstevel@tonic-gate 			}
1331*7c478bd9Sstevel@tonic-gate 			if (scf_service_to_fmri(svc, fmri_buf, fmri_sz) == -1)
1332*7c478bd9Sstevel@tonic-gate 				goto error1;
1333*7c478bd9Sstevel@tonic-gate 			if ((svcfmri = assemble_fmri(h, fmri_buf, pgname,
1334*7c478bd9Sstevel@tonic-gate 			    propname)) == NULL)
1335*7c478bd9Sstevel@tonic-gate 				goto error1;
1336*7c478bd9Sstevel@tonic-gate 			if (scf_handle_decode_fmri(h, svcfmri, NULL, NULL,
1337*7c478bd9Sstevel@tonic-gate 			    NULL, NULL, prop, 0) == -1) {
1338*7c478bd9Sstevel@tonic-gate 				free(svcfmri);
1339*7c478bd9Sstevel@tonic-gate 				goto error1;
1340*7c478bd9Sstevel@tonic-gate 			}
1341*7c478bd9Sstevel@tonic-gate 			free(svcfmri);
1342*7c478bd9Sstevel@tonic-gate 			break;
1343*7c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1344*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1345*7c478bd9Sstevel@tonic-gate 		default:
1346*7c478bd9Sstevel@tonic-gate 			goto error1;
1347*7c478bd9Sstevel@tonic-gate 		}
1348*7c478bd9Sstevel@tonic-gate 	}
1349*7c478bd9Sstevel@tonic-gate 	/*
1350*7c478bd9Sstevel@tonic-gate 	 * At this point, we've successfully pulled the property from the
1351*7c478bd9Sstevel@tonic-gate 	 * datastore, and simply need to copy its innards into an
1352*7c478bd9Sstevel@tonic-gate 	 * scf_simple_prop_t.
1353*7c478bd9Sstevel@tonic-gate 	 */
1354*7c478bd9Sstevel@tonic-gate 	if ((ret = fill_prop(prop, pgname, propname, h)) == NULL)
1355*7c478bd9Sstevel@tonic-gate 		goto error1;
1356*7c478bd9Sstevel@tonic-gate 
1357*7c478bd9Sstevel@tonic-gate 	scf_service_destroy(svc);
1358*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
1359*7c478bd9Sstevel@tonic-gate 	free(fmri_buf);
1360*7c478bd9Sstevel@tonic-gate 	if (local_h)
1361*7c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
1362*7c478bd9Sstevel@tonic-gate 	return (ret);
1363*7c478bd9Sstevel@tonic-gate 
1364*7c478bd9Sstevel@tonic-gate 	/*
1365*7c478bd9Sstevel@tonic-gate 	 * Exit point for a successful call.  Below this line are exit points
1366*7c478bd9Sstevel@tonic-gate 	 * for failures at various stages during the function.
1367*7c478bd9Sstevel@tonic-gate 	 */
1368*7c478bd9Sstevel@tonic-gate 
1369*7c478bd9Sstevel@tonic-gate error1:
1370*7c478bd9Sstevel@tonic-gate 	scf_service_destroy(svc);
1371*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
1372*7c478bd9Sstevel@tonic-gate error2:
1373*7c478bd9Sstevel@tonic-gate 	free(fmri_buf);
1374*7c478bd9Sstevel@tonic-gate 	if (local_h)
1375*7c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
1376*7c478bd9Sstevel@tonic-gate 	return (NULL);
1377*7c478bd9Sstevel@tonic-gate }
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 
1380*7c478bd9Sstevel@tonic-gate void
1381*7c478bd9Sstevel@tonic-gate scf_simple_prop_free(scf_simple_prop_t *prop)
1382*7c478bd9Sstevel@tonic-gate {
1383*7c478bd9Sstevel@tonic-gate 	int i;
1384*7c478bd9Sstevel@tonic-gate 
1385*7c478bd9Sstevel@tonic-gate 	if (prop == NULL)
1386*7c478bd9Sstevel@tonic-gate 		return;
1387*7c478bd9Sstevel@tonic-gate 
1388*7c478bd9Sstevel@tonic-gate 	free(prop->pr_propname);
1389*7c478bd9Sstevel@tonic-gate 	free(prop->pr_pgname);
1390*7c478bd9Sstevel@tonic-gate 	switch (prop->pr_type) {
1391*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_OPAQUE: {
1392*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < prop->pr_numvalues; i++) {
1393*7c478bd9Sstevel@tonic-gate 			free(prop->pr_vallist[i].pv_opaque.o_value);
1394*7c478bd9Sstevel@tonic-gate 		}
1395*7c478bd9Sstevel@tonic-gate 		break;
1396*7c478bd9Sstevel@tonic-gate 	}
1397*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_ASTRING:
1398*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_USTRING:
1399*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOST:
1400*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOSTNAME:
1401*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V4:
1402*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V6:
1403*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_URI:
1404*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_FMRI: {
1405*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < prop->pr_numvalues; i++) {
1406*7c478bd9Sstevel@tonic-gate 			free(prop->pr_vallist[i].pv_str);
1407*7c478bd9Sstevel@tonic-gate 		}
1408*7c478bd9Sstevel@tonic-gate 		break;
1409*7c478bd9Sstevel@tonic-gate 	}
1410*7c478bd9Sstevel@tonic-gate 	default:
1411*7c478bd9Sstevel@tonic-gate 		break;
1412*7c478bd9Sstevel@tonic-gate 	}
1413*7c478bd9Sstevel@tonic-gate 	free(prop->pr_vallist);
1414*7c478bd9Sstevel@tonic-gate 	free(prop);
1415*7c478bd9Sstevel@tonic-gate }
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 
1418*7c478bd9Sstevel@tonic-gate scf_simple_app_props_t *
1419*7c478bd9Sstevel@tonic-gate scf_simple_app_props_get(scf_handle_t *hin, const char *inst_fmri)
1420*7c478bd9Sstevel@tonic-gate {
1421*7c478bd9Sstevel@tonic-gate 	scf_instance_t 		*inst = NULL;
1422*7c478bd9Sstevel@tonic-gate 	scf_service_t 		*svc = NULL;
1423*7c478bd9Sstevel@tonic-gate 	scf_propertygroup_t 	*pg = NULL;
1424*7c478bd9Sstevel@tonic-gate 	scf_property_t 		*prop = NULL;
1425*7c478bd9Sstevel@tonic-gate 	scf_simple_app_props_t	*ret = NULL;
1426*7c478bd9Sstevel@tonic-gate 	scf_iter_t		*pgiter = NULL, *propiter = NULL;
1427*7c478bd9Sstevel@tonic-gate 	struct scf_simple_pg	*thispg = NULL, *nextpg;
1428*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t	*thisprop, *nextprop;
1429*7c478bd9Sstevel@tonic-gate 	scf_handle_t		*h = NULL;
1430*7c478bd9Sstevel@tonic-gate 	int			pgiter_ret, propiter_ret;
1431*7c478bd9Sstevel@tonic-gate 	ssize_t			namelen;
1432*7c478bd9Sstevel@tonic-gate 	char 			*propname = NULL, *pgname = NULL, *sys_fmri;
1433*7c478bd9Sstevel@tonic-gate 	uint8_t			found;
1434*7c478bd9Sstevel@tonic-gate 	boolean_t		local_h = B_TRUE;
1435*7c478bd9Sstevel@tonic-gate 
1436*7c478bd9Sstevel@tonic-gate 	/* If the user passed in a handle, use it. */
1437*7c478bd9Sstevel@tonic-gate 	if (hin != NULL) {
1438*7c478bd9Sstevel@tonic-gate 		h = hin;
1439*7c478bd9Sstevel@tonic-gate 		local_h = B_FALSE;
1440*7c478bd9Sstevel@tonic-gate 	}
1441*7c478bd9Sstevel@tonic-gate 
1442*7c478bd9Sstevel@tonic-gate 	if (local_h && ((h = handle_create()) == NULL))
1443*7c478bd9Sstevel@tonic-gate 		return (NULL);
1444*7c478bd9Sstevel@tonic-gate 
1445*7c478bd9Sstevel@tonic-gate 	if (inst_fmri == NULL) {
1446*7c478bd9Sstevel@tonic-gate 		if ((namelen = scf_myname(h, NULL, 0)) == -1) {
1447*7c478bd9Sstevel@tonic-gate 			if (local_h)
1448*7c478bd9Sstevel@tonic-gate 				scf_handle_destroy(h);
1449*7c478bd9Sstevel@tonic-gate 			return (NULL);
1450*7c478bd9Sstevel@tonic-gate 		}
1451*7c478bd9Sstevel@tonic-gate 		if ((sys_fmri = malloc(namelen + 1)) == NULL) {
1452*7c478bd9Sstevel@tonic-gate 			if (local_h)
1453*7c478bd9Sstevel@tonic-gate 				scf_handle_destroy(h);
1454*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1455*7c478bd9Sstevel@tonic-gate 			return (NULL);
1456*7c478bd9Sstevel@tonic-gate 		}
1457*7c478bd9Sstevel@tonic-gate 		if (scf_myname(h, sys_fmri, namelen + 1) == -1) {
1458*7c478bd9Sstevel@tonic-gate 			if (local_h)
1459*7c478bd9Sstevel@tonic-gate 				scf_handle_destroy(h);
1460*7c478bd9Sstevel@tonic-gate 			free(sys_fmri);
1461*7c478bd9Sstevel@tonic-gate 			return (NULL);
1462*7c478bd9Sstevel@tonic-gate 		}
1463*7c478bd9Sstevel@tonic-gate 	} else {
1464*7c478bd9Sstevel@tonic-gate 		sys_fmri = strdup(inst_fmri);
1465*7c478bd9Sstevel@tonic-gate 	}
1466*7c478bd9Sstevel@tonic-gate 
1467*7c478bd9Sstevel@tonic-gate 	if ((namelen = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH)) == -1) {
1468*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_INTERNAL);
1469*7c478bd9Sstevel@tonic-gate 		return (NULL);
1470*7c478bd9Sstevel@tonic-gate 	}
1471*7c478bd9Sstevel@tonic-gate 
1472*7c478bd9Sstevel@tonic-gate 	if ((inst = scf_instance_create(h)) == NULL ||
1473*7c478bd9Sstevel@tonic-gate 	    (svc = scf_service_create(h)) == NULL ||
1474*7c478bd9Sstevel@tonic-gate 	    (pgiter = scf_iter_create(h)) == NULL ||
1475*7c478bd9Sstevel@tonic-gate 	    (propiter = scf_iter_create(h)) == NULL ||
1476*7c478bd9Sstevel@tonic-gate 	    (pg = scf_pg_create(h)) == NULL ||
1477*7c478bd9Sstevel@tonic-gate 	    (prop = scf_property_create(h)) == NULL)
1478*7c478bd9Sstevel@tonic-gate 		goto error2;
1479*7c478bd9Sstevel@tonic-gate 
1480*7c478bd9Sstevel@tonic-gate 	if (scf_handle_decode_fmri(h, sys_fmri, NULL, svc, inst, NULL, NULL,
1481*7c478bd9Sstevel@tonic-gate 	    SCF_DECODE_FMRI_REQUIRE_INSTANCE) == -1) {
1482*7c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
1483*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1484*7c478bd9Sstevel@tonic-gate 		goto error2;
1485*7c478bd9Sstevel@tonic-gate 	}
1486*7c478bd9Sstevel@tonic-gate 
1487*7c478bd9Sstevel@tonic-gate 	if ((ret = malloc(sizeof (*ret))) == NULL ||
1488*7c478bd9Sstevel@tonic-gate 	    (thispg = malloc(sizeof (*thispg))) == NULL ||
1489*7c478bd9Sstevel@tonic-gate 	    (propname = malloc(namelen)) == NULL ||
1490*7c478bd9Sstevel@tonic-gate 	    (pgname = malloc(namelen)) == NULL) {
1491*7c478bd9Sstevel@tonic-gate 		free(thispg);
1492*7c478bd9Sstevel@tonic-gate 		free(ret);
1493*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1494*7c478bd9Sstevel@tonic-gate 		goto error2;
1495*7c478bd9Sstevel@tonic-gate 	}
1496*7c478bd9Sstevel@tonic-gate 
1497*7c478bd9Sstevel@tonic-gate 	ret->ap_fmri = sys_fmri;
1498*7c478bd9Sstevel@tonic-gate 	thispg->pg_name = NULL;
1499*7c478bd9Sstevel@tonic-gate 	thispg->pg_proplist = NULL;
1500*7c478bd9Sstevel@tonic-gate 	thispg->pg_next = NULL;
1501*7c478bd9Sstevel@tonic-gate 	ret->ap_pglist = thispg;
1502*7c478bd9Sstevel@tonic-gate 
1503*7c478bd9Sstevel@tonic-gate 	if (scf_iter_service_pgs_typed(pgiter, svc, SCF_GROUP_APPLICATION) !=
1504*7c478bd9Sstevel@tonic-gate 	    0) {
1505*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1506*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
1507*7c478bd9Sstevel@tonic-gate 		goto error1;
1508*7c478bd9Sstevel@tonic-gate 	}
1509*7c478bd9Sstevel@tonic-gate 
1510*7c478bd9Sstevel@tonic-gate 	while ((pgiter_ret = scf_iter_next_pg(pgiter, pg)) == 1) {
1511*7c478bd9Sstevel@tonic-gate 		if (thispg->pg_name != NULL) {
1512*7c478bd9Sstevel@tonic-gate 			if ((nextpg = malloc(sizeof (*nextpg))) == NULL) {
1513*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1514*7c478bd9Sstevel@tonic-gate 				goto error1;
1515*7c478bd9Sstevel@tonic-gate 			}
1516*7c478bd9Sstevel@tonic-gate 			thispg->pg_next = nextpg;
1517*7c478bd9Sstevel@tonic-gate 			thispg = nextpg;
1518*7c478bd9Sstevel@tonic-gate 		} else {
1519*7c478bd9Sstevel@tonic-gate 			/* This is the first iteration */
1520*7c478bd9Sstevel@tonic-gate 			nextpg = thispg;
1521*7c478bd9Sstevel@tonic-gate 		}
1522*7c478bd9Sstevel@tonic-gate 
1523*7c478bd9Sstevel@tonic-gate 		if ((nextpg->pg_name = malloc(namelen)) == NULL) {
1524*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1525*7c478bd9Sstevel@tonic-gate 			goto error1;
1526*7c478bd9Sstevel@tonic-gate 		}
1527*7c478bd9Sstevel@tonic-gate 
1528*7c478bd9Sstevel@tonic-gate 		if (scf_pg_get_name(pg, nextpg->pg_name, namelen) < 0) {
1529*7c478bd9Sstevel@tonic-gate 			if (scf_error() == SCF_ERROR_NOT_SET)
1530*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
1531*7c478bd9Sstevel@tonic-gate 			goto error1;
1532*7c478bd9Sstevel@tonic-gate 		}
1533*7c478bd9Sstevel@tonic-gate 
1534*7c478bd9Sstevel@tonic-gate 		nextpg->pg_next = NULL;
1535*7c478bd9Sstevel@tonic-gate 		nextpg->pg_proplist = NULL;
1536*7c478bd9Sstevel@tonic-gate 		thisprop = NULL;
1537*7c478bd9Sstevel@tonic-gate 
1538*7c478bd9Sstevel@tonic-gate 		scf_iter_reset(propiter);
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate 		if (scf_iter_pg_properties(propiter, pg) != 0) {
1541*7c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1542*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
1543*7c478bd9Sstevel@tonic-gate 			goto error1;
1544*7c478bd9Sstevel@tonic-gate 		}
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 		while ((propiter_ret = scf_iter_next_property(propiter, prop))
1547*7c478bd9Sstevel@tonic-gate 		    == 1) {
1548*7c478bd9Sstevel@tonic-gate 			if (scf_property_get_name(prop, propname, namelen) <
1549*7c478bd9Sstevel@tonic-gate 			    0) {
1550*7c478bd9Sstevel@tonic-gate 				if (scf_error() == SCF_ERROR_NOT_SET)
1551*7c478bd9Sstevel@tonic-gate 					(void) scf_set_error(
1552*7c478bd9Sstevel@tonic-gate 					    SCF_ERROR_INTERNAL);
1553*7c478bd9Sstevel@tonic-gate 				goto error1;
1554*7c478bd9Sstevel@tonic-gate 			}
1555*7c478bd9Sstevel@tonic-gate 			if (thisprop != NULL) {
1556*7c478bd9Sstevel@tonic-gate 				if ((nextprop = fill_prop(prop,
1557*7c478bd9Sstevel@tonic-gate 				    nextpg->pg_name, propname, h)) == NULL)
1558*7c478bd9Sstevel@tonic-gate 					goto error1;
1559*7c478bd9Sstevel@tonic-gate 				thisprop->pr_next = nextprop;
1560*7c478bd9Sstevel@tonic-gate 				thisprop = nextprop;
1561*7c478bd9Sstevel@tonic-gate 			} else {
1562*7c478bd9Sstevel@tonic-gate 				/* This is the first iteration */
1563*7c478bd9Sstevel@tonic-gate 				if ((thisprop = fill_prop(prop,
1564*7c478bd9Sstevel@tonic-gate 				    nextpg->pg_name, propname, h)) == NULL)
1565*7c478bd9Sstevel@tonic-gate 					goto error1;
1566*7c478bd9Sstevel@tonic-gate 				nextpg->pg_proplist = thisprop;
1567*7c478bd9Sstevel@tonic-gate 				nextprop = thisprop;
1568*7c478bd9Sstevel@tonic-gate 			}
1569*7c478bd9Sstevel@tonic-gate 			nextprop->pr_pg = nextpg;
1570*7c478bd9Sstevel@tonic-gate 			nextprop->pr_next = NULL;
1571*7c478bd9Sstevel@tonic-gate 		}
1572*7c478bd9Sstevel@tonic-gate 
1573*7c478bd9Sstevel@tonic-gate 		if (propiter_ret == -1) {
1574*7c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1575*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
1576*7c478bd9Sstevel@tonic-gate 			goto error1;
1577*7c478bd9Sstevel@tonic-gate 		}
1578*7c478bd9Sstevel@tonic-gate 	}
1579*7c478bd9Sstevel@tonic-gate 
1580*7c478bd9Sstevel@tonic-gate 	if (pgiter_ret == -1) {
1581*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1582*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
1583*7c478bd9Sstevel@tonic-gate 		goto error1;
1584*7c478bd9Sstevel@tonic-gate 	}
1585*7c478bd9Sstevel@tonic-gate 
1586*7c478bd9Sstevel@tonic-gate 	/*
1587*7c478bd9Sstevel@tonic-gate 	 * At this point, we've filled the scf_simple_app_props_t with all the
1588*7c478bd9Sstevel@tonic-gate 	 * properties at the service level.  Now we iterate over all the
1589*7c478bd9Sstevel@tonic-gate 	 * properties at the instance level, overwriting any duplicate
1590*7c478bd9Sstevel@tonic-gate 	 * properties, in order to provide service/instance composition.
1591*7c478bd9Sstevel@tonic-gate 	 */
1592*7c478bd9Sstevel@tonic-gate 
1593*7c478bd9Sstevel@tonic-gate 	scf_iter_reset(pgiter);
1594*7c478bd9Sstevel@tonic-gate 	scf_iter_reset(propiter);
1595*7c478bd9Sstevel@tonic-gate 
1596*7c478bd9Sstevel@tonic-gate 	if (scf_iter_instance_pgs_typed(pgiter, inst, SCF_GROUP_APPLICATION)
1597*7c478bd9Sstevel@tonic-gate 	    != 0) {
1598*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1599*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
1600*7c478bd9Sstevel@tonic-gate 		goto error1;
1601*7c478bd9Sstevel@tonic-gate 	}
1602*7c478bd9Sstevel@tonic-gate 
1603*7c478bd9Sstevel@tonic-gate 	while ((pgiter_ret = scf_iter_next_pg(pgiter, pg)) == 1) {
1604*7c478bd9Sstevel@tonic-gate 
1605*7c478bd9Sstevel@tonic-gate 		thispg = ret->ap_pglist;
1606*7c478bd9Sstevel@tonic-gate 		found = 0;
1607*7c478bd9Sstevel@tonic-gate 
1608*7c478bd9Sstevel@tonic-gate 		/*
1609*7c478bd9Sstevel@tonic-gate 		 * Find either the end of the list, so we can append the
1610*7c478bd9Sstevel@tonic-gate 		 * property group, or an existing property group that matches
1611*7c478bd9Sstevel@tonic-gate 		 * it, so we can insert/overwrite its properties.
1612*7c478bd9Sstevel@tonic-gate 		 */
1613*7c478bd9Sstevel@tonic-gate 
1614*7c478bd9Sstevel@tonic-gate 		if (scf_pg_get_name(pg, pgname, namelen) < 0) {
1615*7c478bd9Sstevel@tonic-gate 			if (scf_error() == SCF_ERROR_NOT_SET)
1616*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
1617*7c478bd9Sstevel@tonic-gate 			goto error1;
1618*7c478bd9Sstevel@tonic-gate 		}
1619*7c478bd9Sstevel@tonic-gate 
1620*7c478bd9Sstevel@tonic-gate 		while ((thispg != NULL) && (thispg->pg_name != NULL)) {
1621*7c478bd9Sstevel@tonic-gate 			if (strcmp(thispg->pg_name, pgname) == 0) {
1622*7c478bd9Sstevel@tonic-gate 				found = 1;
1623*7c478bd9Sstevel@tonic-gate 				break;
1624*7c478bd9Sstevel@tonic-gate 			}
1625*7c478bd9Sstevel@tonic-gate 			if (thispg->pg_next == NULL)
1626*7c478bd9Sstevel@tonic-gate 				break;
1627*7c478bd9Sstevel@tonic-gate 
1628*7c478bd9Sstevel@tonic-gate 			thispg = thispg->pg_next;
1629*7c478bd9Sstevel@tonic-gate 		}
1630*7c478bd9Sstevel@tonic-gate 
1631*7c478bd9Sstevel@tonic-gate 		scf_iter_reset(propiter);
1632*7c478bd9Sstevel@tonic-gate 
1633*7c478bd9Sstevel@tonic-gate 		if (scf_iter_pg_properties(propiter, pg) != 0) {
1634*7c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1635*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_INTERNAL);
1636*7c478bd9Sstevel@tonic-gate 			goto error1;
1637*7c478bd9Sstevel@tonic-gate 		}
1638*7c478bd9Sstevel@tonic-gate 
1639*7c478bd9Sstevel@tonic-gate 		if (found) {
1640*7c478bd9Sstevel@tonic-gate 			/*
1641*7c478bd9Sstevel@tonic-gate 			 * insert_app_props inserts or overwrites the
1642*7c478bd9Sstevel@tonic-gate 			 * properties in thispg.
1643*7c478bd9Sstevel@tonic-gate 			 */
1644*7c478bd9Sstevel@tonic-gate 
1645*7c478bd9Sstevel@tonic-gate 			if (insert_app_props(propiter, pgname, propname,
1646*7c478bd9Sstevel@tonic-gate 			    thispg, prop, namelen, h) == -1)
1647*7c478bd9Sstevel@tonic-gate 				goto error1;
1648*7c478bd9Sstevel@tonic-gate 
1649*7c478bd9Sstevel@tonic-gate 		} else {
1650*7c478bd9Sstevel@tonic-gate 			/*
1651*7c478bd9Sstevel@tonic-gate 			 * If the property group wasn't found, we're adding
1652*7c478bd9Sstevel@tonic-gate 			 * a newly allocated property group to the end of the
1653*7c478bd9Sstevel@tonic-gate 			 * list.
1654*7c478bd9Sstevel@tonic-gate 			 */
1655*7c478bd9Sstevel@tonic-gate 
1656*7c478bd9Sstevel@tonic-gate 			if ((nextpg = malloc(sizeof (*nextpg))) == NULL) {
1657*7c478bd9Sstevel@tonic-gate 				(void) scf_set_error(SCF_ERROR_NO_MEMORY);
1658*7c478bd9Sstevel@tonic-gate 				goto error1;
1659*7c478bd9Sstevel@tonic-gate 			}
1660*7c478bd9Sstevel@tonic-gate 			nextpg->pg_next = NULL;
1661*7c478bd9Sstevel@tonic-gate 			nextpg->pg_proplist = NULL;
1662*7c478bd9Sstevel@tonic-gate 			thisprop = NULL;
1663*7c478bd9Sstevel@tonic-gate 
1664*7c478bd9Sstevel@tonic-gate 			if ((nextpg->pg_name = strdup(pgname)) == NULL) {
1665*7c478bd9Sstevel@tonic-gate 				free(nextpg);
1666*7c478bd9Sstevel@tonic-gate 				goto error1;
1667*7c478bd9Sstevel@tonic-gate 			}
1668*7c478bd9Sstevel@tonic-gate 
1669*7c478bd9Sstevel@tonic-gate 			if (thispg->pg_name == NULL) {
1670*7c478bd9Sstevel@tonic-gate 				free(thispg);
1671*7c478bd9Sstevel@tonic-gate 				ret->ap_pglist = nextpg;
1672*7c478bd9Sstevel@tonic-gate 			} else {
1673*7c478bd9Sstevel@tonic-gate 				thispg->pg_next = nextpg;
1674*7c478bd9Sstevel@tonic-gate 			}
1675*7c478bd9Sstevel@tonic-gate 
1676*7c478bd9Sstevel@tonic-gate 			while ((propiter_ret =
1677*7c478bd9Sstevel@tonic-gate 			    scf_iter_next_property(propiter, prop)) == 1) {
1678*7c478bd9Sstevel@tonic-gate 				if (scf_property_get_name(prop, propname,
1679*7c478bd9Sstevel@tonic-gate 				    namelen) < 0) {
1680*7c478bd9Sstevel@tonic-gate 					if (scf_error() == SCF_ERROR_NOT_SET)
1681*7c478bd9Sstevel@tonic-gate 						(void) scf_set_error(
1682*7c478bd9Sstevel@tonic-gate 						    SCF_ERROR_INTERNAL);
1683*7c478bd9Sstevel@tonic-gate 					goto error1;
1684*7c478bd9Sstevel@tonic-gate 				}
1685*7c478bd9Sstevel@tonic-gate 				if (thisprop != NULL) {
1686*7c478bd9Sstevel@tonic-gate 					if ((nextprop = fill_prop(prop,
1687*7c478bd9Sstevel@tonic-gate 					    pgname, propname, h)) ==
1688*7c478bd9Sstevel@tonic-gate 					    NULL)
1689*7c478bd9Sstevel@tonic-gate 						goto error1;
1690*7c478bd9Sstevel@tonic-gate 					thisprop->pr_next = nextprop;
1691*7c478bd9Sstevel@tonic-gate 					thisprop = nextprop;
1692*7c478bd9Sstevel@tonic-gate 				} else {
1693*7c478bd9Sstevel@tonic-gate 					/* This is the first iteration */
1694*7c478bd9Sstevel@tonic-gate 					if ((thisprop = fill_prop(prop,
1695*7c478bd9Sstevel@tonic-gate 					    pgname, propname, h)) ==
1696*7c478bd9Sstevel@tonic-gate 					    NULL)
1697*7c478bd9Sstevel@tonic-gate 						goto error1;
1698*7c478bd9Sstevel@tonic-gate 					nextpg->pg_proplist = thisprop;
1699*7c478bd9Sstevel@tonic-gate 					nextprop = thisprop;
1700*7c478bd9Sstevel@tonic-gate 				}
1701*7c478bd9Sstevel@tonic-gate 				nextprop->pr_pg = nextpg;
1702*7c478bd9Sstevel@tonic-gate 				nextprop->pr_next = NULL;
1703*7c478bd9Sstevel@tonic-gate 			}
1704*7c478bd9Sstevel@tonic-gate 
1705*7c478bd9Sstevel@tonic-gate 			if (propiter_ret == -1) {
1706*7c478bd9Sstevel@tonic-gate 				if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1707*7c478bd9Sstevel@tonic-gate 					(void) scf_set_error(
1708*7c478bd9Sstevel@tonic-gate 					    SCF_ERROR_INTERNAL);
1709*7c478bd9Sstevel@tonic-gate 				goto error1;
1710*7c478bd9Sstevel@tonic-gate 			}
1711*7c478bd9Sstevel@tonic-gate 		}
1712*7c478bd9Sstevel@tonic-gate 
1713*7c478bd9Sstevel@tonic-gate 	}
1714*7c478bd9Sstevel@tonic-gate 
1715*7c478bd9Sstevel@tonic-gate 	if (pgiter_ret == -1) {
1716*7c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
1717*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_INTERNAL);
1718*7c478bd9Sstevel@tonic-gate 		goto error1;
1719*7c478bd9Sstevel@tonic-gate 	}
1720*7c478bd9Sstevel@tonic-gate 
1721*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(pgiter);
1722*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(propiter);
1723*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
1724*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
1725*7c478bd9Sstevel@tonic-gate 	scf_instance_destroy(inst);
1726*7c478bd9Sstevel@tonic-gate 	scf_service_destroy(svc);
1727*7c478bd9Sstevel@tonic-gate 	free(propname);
1728*7c478bd9Sstevel@tonic-gate 	free(pgname);
1729*7c478bd9Sstevel@tonic-gate 	if (local_h)
1730*7c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
1731*7c478bd9Sstevel@tonic-gate 
1732*7c478bd9Sstevel@tonic-gate 	if (ret->ap_pglist->pg_name == NULL)
1733*7c478bd9Sstevel@tonic-gate 		return (NULL);
1734*7c478bd9Sstevel@tonic-gate 
1735*7c478bd9Sstevel@tonic-gate 	return (ret);
1736*7c478bd9Sstevel@tonic-gate 
1737*7c478bd9Sstevel@tonic-gate 	/*
1738*7c478bd9Sstevel@tonic-gate 	 * Exit point for a successful call.  Below this line are exit points
1739*7c478bd9Sstevel@tonic-gate 	 * for failures at various stages during the function.
1740*7c478bd9Sstevel@tonic-gate 	 */
1741*7c478bd9Sstevel@tonic-gate 
1742*7c478bd9Sstevel@tonic-gate error1:
1743*7c478bd9Sstevel@tonic-gate 	scf_simple_app_props_free(ret);
1744*7c478bd9Sstevel@tonic-gate 
1745*7c478bd9Sstevel@tonic-gate error2:
1746*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(pgiter);
1747*7c478bd9Sstevel@tonic-gate 	scf_iter_destroy(propiter);
1748*7c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
1749*7c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
1750*7c478bd9Sstevel@tonic-gate 	scf_instance_destroy(inst);
1751*7c478bd9Sstevel@tonic-gate 	scf_service_destroy(svc);
1752*7c478bd9Sstevel@tonic-gate 	free(propname);
1753*7c478bd9Sstevel@tonic-gate 	free(pgname);
1754*7c478bd9Sstevel@tonic-gate 	if (local_h)
1755*7c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
1756*7c478bd9Sstevel@tonic-gate 	return (NULL);
1757*7c478bd9Sstevel@tonic-gate }
1758*7c478bd9Sstevel@tonic-gate 
1759*7c478bd9Sstevel@tonic-gate 
1760*7c478bd9Sstevel@tonic-gate void
1761*7c478bd9Sstevel@tonic-gate scf_simple_app_props_free(scf_simple_app_props_t *propblock)
1762*7c478bd9Sstevel@tonic-gate {
1763*7c478bd9Sstevel@tonic-gate 	struct scf_simple_pg 	*pgthis, *pgnext;
1764*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t 	*propthis, *propnext;
1765*7c478bd9Sstevel@tonic-gate 
1766*7c478bd9Sstevel@tonic-gate 	if ((propblock == NULL) || (propblock->ap_pglist == NULL))
1767*7c478bd9Sstevel@tonic-gate 		return;
1768*7c478bd9Sstevel@tonic-gate 
1769*7c478bd9Sstevel@tonic-gate 	for (pgthis = propblock->ap_pglist; pgthis != NULL; pgthis = pgnext) {
1770*7c478bd9Sstevel@tonic-gate 		pgnext = pgthis->pg_next;
1771*7c478bd9Sstevel@tonic-gate 
1772*7c478bd9Sstevel@tonic-gate 		propthis = pgthis->pg_proplist;
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate 		while (propthis != NULL) {
1775*7c478bd9Sstevel@tonic-gate 			propnext = propthis->pr_next;
1776*7c478bd9Sstevel@tonic-gate 			scf_simple_prop_free(propthis);
1777*7c478bd9Sstevel@tonic-gate 			propthis = propnext;
1778*7c478bd9Sstevel@tonic-gate 		}
1779*7c478bd9Sstevel@tonic-gate 
1780*7c478bd9Sstevel@tonic-gate 		free(pgthis->pg_name);
1781*7c478bd9Sstevel@tonic-gate 		free(pgthis);
1782*7c478bd9Sstevel@tonic-gate 	}
1783*7c478bd9Sstevel@tonic-gate 
1784*7c478bd9Sstevel@tonic-gate 	free(propblock->ap_fmri);
1785*7c478bd9Sstevel@tonic-gate 	free(propblock);
1786*7c478bd9Sstevel@tonic-gate }
1787*7c478bd9Sstevel@tonic-gate 
1788*7c478bd9Sstevel@tonic-gate const scf_simple_prop_t *
1789*7c478bd9Sstevel@tonic-gate scf_simple_app_props_next(const scf_simple_app_props_t *propblock,
1790*7c478bd9Sstevel@tonic-gate     scf_simple_prop_t *last)
1791*7c478bd9Sstevel@tonic-gate {
1792*7c478bd9Sstevel@tonic-gate 	struct scf_simple_pg 	*this;
1793*7c478bd9Sstevel@tonic-gate 
1794*7c478bd9Sstevel@tonic-gate 	if (propblock == NULL) {
1795*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_SET);
1796*7c478bd9Sstevel@tonic-gate 		return (NULL);
1797*7c478bd9Sstevel@tonic-gate 	}
1798*7c478bd9Sstevel@tonic-gate 
1799*7c478bd9Sstevel@tonic-gate 	this = propblock->ap_pglist;
1800*7c478bd9Sstevel@tonic-gate 
1801*7c478bd9Sstevel@tonic-gate 	/*
1802*7c478bd9Sstevel@tonic-gate 	 * We're looking for the first property in this block if last is
1803*7c478bd9Sstevel@tonic-gate 	 * NULL
1804*7c478bd9Sstevel@tonic-gate 	 */
1805*7c478bd9Sstevel@tonic-gate 
1806*7c478bd9Sstevel@tonic-gate 	if (last == NULL) {
1807*7c478bd9Sstevel@tonic-gate 		/* An empty pglist is legal, it just means no properties */
1808*7c478bd9Sstevel@tonic-gate 		if (this == NULL) {
1809*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_NONE);
1810*7c478bd9Sstevel@tonic-gate 			return (NULL);
1811*7c478bd9Sstevel@tonic-gate 		}
1812*7c478bd9Sstevel@tonic-gate 		/*
1813*7c478bd9Sstevel@tonic-gate 		 * Walk until we find a pg with a property in it, or we run
1814*7c478bd9Sstevel@tonic-gate 		 * out of property groups.
1815*7c478bd9Sstevel@tonic-gate 		 */
1816*7c478bd9Sstevel@tonic-gate 		while ((this->pg_proplist == NULL) && (this->pg_next != NULL))
1817*7c478bd9Sstevel@tonic-gate 			this = this->pg_next;
1818*7c478bd9Sstevel@tonic-gate 
1819*7c478bd9Sstevel@tonic-gate 		if (this->pg_proplist == NULL) {
1820*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_NONE);
1821*7c478bd9Sstevel@tonic-gate 			return (NULL);
1822*7c478bd9Sstevel@tonic-gate 		}
1823*7c478bd9Sstevel@tonic-gate 
1824*7c478bd9Sstevel@tonic-gate 		return (this->pg_proplist);
1825*7c478bd9Sstevel@tonic-gate 
1826*7c478bd9Sstevel@tonic-gate 	}
1827*7c478bd9Sstevel@tonic-gate 	/*
1828*7c478bd9Sstevel@tonic-gate 	 * If last isn't NULL, then return the next prop in the property group,
1829*7c478bd9Sstevel@tonic-gate 	 * or walk the property groups until we find another property, or
1830*7c478bd9Sstevel@tonic-gate 	 * run out of property groups.
1831*7c478bd9Sstevel@tonic-gate 	 */
1832*7c478bd9Sstevel@tonic-gate 	if (last->pr_next != NULL)
1833*7c478bd9Sstevel@tonic-gate 		return (last->pr_next);
1834*7c478bd9Sstevel@tonic-gate 
1835*7c478bd9Sstevel@tonic-gate 	if (last->pr_pg->pg_next == NULL) {
1836*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NONE);
1837*7c478bd9Sstevel@tonic-gate 		return (NULL);
1838*7c478bd9Sstevel@tonic-gate 	}
1839*7c478bd9Sstevel@tonic-gate 
1840*7c478bd9Sstevel@tonic-gate 	this = last->pr_pg->pg_next;
1841*7c478bd9Sstevel@tonic-gate 
1842*7c478bd9Sstevel@tonic-gate 	while ((this->pg_proplist == NULL) && (this->pg_next != NULL))
1843*7c478bd9Sstevel@tonic-gate 		this = this->pg_next;
1844*7c478bd9Sstevel@tonic-gate 
1845*7c478bd9Sstevel@tonic-gate 	if (this->pg_proplist == NULL) {
1846*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NONE);
1847*7c478bd9Sstevel@tonic-gate 		return (NULL);
1848*7c478bd9Sstevel@tonic-gate 	}
1849*7c478bd9Sstevel@tonic-gate 
1850*7c478bd9Sstevel@tonic-gate 	return (this->pg_proplist);
1851*7c478bd9Sstevel@tonic-gate }
1852*7c478bd9Sstevel@tonic-gate 
1853*7c478bd9Sstevel@tonic-gate const scf_simple_prop_t *
1854*7c478bd9Sstevel@tonic-gate scf_simple_app_props_search(const scf_simple_app_props_t *propblock,
1855*7c478bd9Sstevel@tonic-gate     const char *pgname, const char *propname)
1856*7c478bd9Sstevel@tonic-gate {
1857*7c478bd9Sstevel@tonic-gate 	struct scf_simple_pg 	*pg;
1858*7c478bd9Sstevel@tonic-gate 	scf_simple_prop_t 	*prop;
1859*7c478bd9Sstevel@tonic-gate 
1860*7c478bd9Sstevel@tonic-gate 	if ((propblock == NULL) || (propname == NULL)) {
1861*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_SET);
1862*7c478bd9Sstevel@tonic-gate 		return (NULL);
1863*7c478bd9Sstevel@tonic-gate 	}
1864*7c478bd9Sstevel@tonic-gate 
1865*7c478bd9Sstevel@tonic-gate 	pg = propblock->ap_pglist;
1866*7c478bd9Sstevel@tonic-gate 
1867*7c478bd9Sstevel@tonic-gate 	/*
1868*7c478bd9Sstevel@tonic-gate 	 * If pgname is NULL, we're searching the default application
1869*7c478bd9Sstevel@tonic-gate 	 * property group, otherwise we look for the specified group.
1870*7c478bd9Sstevel@tonic-gate 	 */
1871*7c478bd9Sstevel@tonic-gate 	if (pgname == NULL) {
1872*7c478bd9Sstevel@tonic-gate 		while ((pg != NULL) &&
1873*7c478bd9Sstevel@tonic-gate 		    (strcmp(SCF_PG_APP_DEFAULT, pg->pg_name) != 0))
1874*7c478bd9Sstevel@tonic-gate 			pg = pg->pg_next;
1875*7c478bd9Sstevel@tonic-gate 	} else {
1876*7c478bd9Sstevel@tonic-gate 		while ((pg != NULL) && (strcmp(pgname, pg->pg_name) != 0))
1877*7c478bd9Sstevel@tonic-gate 			pg = pg->pg_next;
1878*7c478bd9Sstevel@tonic-gate 	}
1879*7c478bd9Sstevel@tonic-gate 
1880*7c478bd9Sstevel@tonic-gate 	if (pg == NULL) {
1881*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
1882*7c478bd9Sstevel@tonic-gate 		return (NULL);
1883*7c478bd9Sstevel@tonic-gate 	}
1884*7c478bd9Sstevel@tonic-gate 
1885*7c478bd9Sstevel@tonic-gate 	prop = pg->pg_proplist;
1886*7c478bd9Sstevel@tonic-gate 
1887*7c478bd9Sstevel@tonic-gate 	while ((prop != NULL) && (strcmp(propname, prop->pr_propname) != 0))
1888*7c478bd9Sstevel@tonic-gate 		prop = prop->pr_next;
1889*7c478bd9Sstevel@tonic-gate 
1890*7c478bd9Sstevel@tonic-gate 	if (prop == NULL) {
1891*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_FOUND);
1892*7c478bd9Sstevel@tonic-gate 		return (NULL);
1893*7c478bd9Sstevel@tonic-gate 	}
1894*7c478bd9Sstevel@tonic-gate 
1895*7c478bd9Sstevel@tonic-gate 	return (prop);
1896*7c478bd9Sstevel@tonic-gate }
1897*7c478bd9Sstevel@tonic-gate 
1898*7c478bd9Sstevel@tonic-gate void
1899*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_reset(scf_simple_prop_t *prop)
1900*7c478bd9Sstevel@tonic-gate {
1901*7c478bd9Sstevel@tonic-gate 	if (prop == NULL)
1902*7c478bd9Sstevel@tonic-gate 		return;
1903*7c478bd9Sstevel@tonic-gate 	prop->pr_iter = 0;
1904*7c478bd9Sstevel@tonic-gate }
1905*7c478bd9Sstevel@tonic-gate 
1906*7c478bd9Sstevel@tonic-gate ssize_t
1907*7c478bd9Sstevel@tonic-gate scf_simple_prop_numvalues(const scf_simple_prop_t *prop)
1908*7c478bd9Sstevel@tonic-gate {
1909*7c478bd9Sstevel@tonic-gate 	if (prop == NULL)
1910*7c478bd9Sstevel@tonic-gate 		return (scf_set_error(SCF_ERROR_NOT_SET));
1911*7c478bd9Sstevel@tonic-gate 
1912*7c478bd9Sstevel@tonic-gate 	return (prop->pr_numvalues);
1913*7c478bd9Sstevel@tonic-gate }
1914*7c478bd9Sstevel@tonic-gate 
1915*7c478bd9Sstevel@tonic-gate 
1916*7c478bd9Sstevel@tonic-gate scf_type_t
1917*7c478bd9Sstevel@tonic-gate scf_simple_prop_type(const scf_simple_prop_t *prop)
1918*7c478bd9Sstevel@tonic-gate {
1919*7c478bd9Sstevel@tonic-gate 	if (prop == NULL)
1920*7c478bd9Sstevel@tonic-gate 		return (scf_set_error(SCF_ERROR_NOT_SET));
1921*7c478bd9Sstevel@tonic-gate 
1922*7c478bd9Sstevel@tonic-gate 	return (prop->pr_type);
1923*7c478bd9Sstevel@tonic-gate }
1924*7c478bd9Sstevel@tonic-gate 
1925*7c478bd9Sstevel@tonic-gate 
1926*7c478bd9Sstevel@tonic-gate char *
1927*7c478bd9Sstevel@tonic-gate scf_simple_prop_name(const scf_simple_prop_t *prop)
1928*7c478bd9Sstevel@tonic-gate {
1929*7c478bd9Sstevel@tonic-gate 	if ((prop == NULL) || (prop->pr_propname == NULL)) {
1930*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_SET);
1931*7c478bd9Sstevel@tonic-gate 		return (NULL);
1932*7c478bd9Sstevel@tonic-gate 	}
1933*7c478bd9Sstevel@tonic-gate 
1934*7c478bd9Sstevel@tonic-gate 	return (prop->pr_propname);
1935*7c478bd9Sstevel@tonic-gate }
1936*7c478bd9Sstevel@tonic-gate 
1937*7c478bd9Sstevel@tonic-gate 
1938*7c478bd9Sstevel@tonic-gate char *
1939*7c478bd9Sstevel@tonic-gate scf_simple_prop_pgname(const scf_simple_prop_t *prop)
1940*7c478bd9Sstevel@tonic-gate {
1941*7c478bd9Sstevel@tonic-gate 	if ((prop == NULL) || (prop->pr_pgname == NULL)) {
1942*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_SET);
1943*7c478bd9Sstevel@tonic-gate 		return (NULL);
1944*7c478bd9Sstevel@tonic-gate 	}
1945*7c478bd9Sstevel@tonic-gate 
1946*7c478bd9Sstevel@tonic-gate 	return (prop->pr_pgname);
1947*7c478bd9Sstevel@tonic-gate }
1948*7c478bd9Sstevel@tonic-gate 
1949*7c478bd9Sstevel@tonic-gate 
1950*7c478bd9Sstevel@tonic-gate static union scf_simple_prop_val *
1951*7c478bd9Sstevel@tonic-gate scf_next_val(scf_simple_prop_t *prop, scf_type_t type)
1952*7c478bd9Sstevel@tonic-gate {
1953*7c478bd9Sstevel@tonic-gate 	if (prop == NULL) {
1954*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NOT_SET);
1955*7c478bd9Sstevel@tonic-gate 		return (NULL);
1956*7c478bd9Sstevel@tonic-gate 	}
1957*7c478bd9Sstevel@tonic-gate 
1958*7c478bd9Sstevel@tonic-gate 	switch (prop->pr_type) {
1959*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_USTRING:
1960*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOST:
1961*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOSTNAME:
1962*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V4:
1963*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V6:
1964*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_URI:
1965*7c478bd9Sstevel@tonic-gate 	case SCF_TYPE_FMRI: {
1966*7c478bd9Sstevel@tonic-gate 		if (type != SCF_TYPE_USTRING) {
1967*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_TYPE_MISMATCH);
1968*7c478bd9Sstevel@tonic-gate 			return (NULL);
1969*7c478bd9Sstevel@tonic-gate 		}
1970*7c478bd9Sstevel@tonic-gate 		break;
1971*7c478bd9Sstevel@tonic-gate 		}
1972*7c478bd9Sstevel@tonic-gate 	default: {
1973*7c478bd9Sstevel@tonic-gate 		if (type != prop->pr_type) {
1974*7c478bd9Sstevel@tonic-gate 			(void) scf_set_error(SCF_ERROR_TYPE_MISMATCH);
1975*7c478bd9Sstevel@tonic-gate 			return (NULL);
1976*7c478bd9Sstevel@tonic-gate 		}
1977*7c478bd9Sstevel@tonic-gate 		break;
1978*7c478bd9Sstevel@tonic-gate 		}
1979*7c478bd9Sstevel@tonic-gate 	}
1980*7c478bd9Sstevel@tonic-gate 
1981*7c478bd9Sstevel@tonic-gate 	if (prop->pr_iter >= prop->pr_numvalues) {
1982*7c478bd9Sstevel@tonic-gate 		(void) scf_set_error(SCF_ERROR_NONE);
1983*7c478bd9Sstevel@tonic-gate 		return (NULL);
1984*7c478bd9Sstevel@tonic-gate 	}
1985*7c478bd9Sstevel@tonic-gate 
1986*7c478bd9Sstevel@tonic-gate 	return (&prop->pr_vallist[prop->pr_iter++]);
1987*7c478bd9Sstevel@tonic-gate }
1988*7c478bd9Sstevel@tonic-gate 
1989*7c478bd9Sstevel@tonic-gate 
1990*7c478bd9Sstevel@tonic-gate uint8_t *
1991*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_boolean(scf_simple_prop_t *prop)
1992*7c478bd9Sstevel@tonic-gate {
1993*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
1994*7c478bd9Sstevel@tonic-gate 
1995*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_BOOLEAN);
1996*7c478bd9Sstevel@tonic-gate 
1997*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
1998*7c478bd9Sstevel@tonic-gate 		return (NULL);
1999*7c478bd9Sstevel@tonic-gate 
2000*7c478bd9Sstevel@tonic-gate 	return (&ret->pv_bool);
2001*7c478bd9Sstevel@tonic-gate }
2002*7c478bd9Sstevel@tonic-gate 
2003*7c478bd9Sstevel@tonic-gate 
2004*7c478bd9Sstevel@tonic-gate uint64_t *
2005*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_count(scf_simple_prop_t *prop)
2006*7c478bd9Sstevel@tonic-gate {
2007*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
2008*7c478bd9Sstevel@tonic-gate 
2009*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_COUNT);
2010*7c478bd9Sstevel@tonic-gate 
2011*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
2012*7c478bd9Sstevel@tonic-gate 		return (NULL);
2013*7c478bd9Sstevel@tonic-gate 
2014*7c478bd9Sstevel@tonic-gate 	return (&ret->pv_uint);
2015*7c478bd9Sstevel@tonic-gate }
2016*7c478bd9Sstevel@tonic-gate 
2017*7c478bd9Sstevel@tonic-gate 
2018*7c478bd9Sstevel@tonic-gate int64_t *
2019*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_integer(scf_simple_prop_t *prop)
2020*7c478bd9Sstevel@tonic-gate {
2021*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
2022*7c478bd9Sstevel@tonic-gate 
2023*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_INTEGER);
2024*7c478bd9Sstevel@tonic-gate 
2025*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
2026*7c478bd9Sstevel@tonic-gate 		return (NULL);
2027*7c478bd9Sstevel@tonic-gate 
2028*7c478bd9Sstevel@tonic-gate 	return (&ret->pv_int);
2029*7c478bd9Sstevel@tonic-gate }
2030*7c478bd9Sstevel@tonic-gate 
2031*7c478bd9Sstevel@tonic-gate int64_t *
2032*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_time(scf_simple_prop_t *prop, int32_t *nsec)
2033*7c478bd9Sstevel@tonic-gate {
2034*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
2035*7c478bd9Sstevel@tonic-gate 
2036*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_TIME);
2037*7c478bd9Sstevel@tonic-gate 
2038*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
2039*7c478bd9Sstevel@tonic-gate 		return (NULL);
2040*7c478bd9Sstevel@tonic-gate 
2041*7c478bd9Sstevel@tonic-gate 	if (nsec != NULL)
2042*7c478bd9Sstevel@tonic-gate 		*nsec = ret->pv_time.t_nsec;
2043*7c478bd9Sstevel@tonic-gate 
2044*7c478bd9Sstevel@tonic-gate 	return (&ret->pv_time.t_sec);
2045*7c478bd9Sstevel@tonic-gate }
2046*7c478bd9Sstevel@tonic-gate 
2047*7c478bd9Sstevel@tonic-gate char *
2048*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_astring(scf_simple_prop_t *prop)
2049*7c478bd9Sstevel@tonic-gate {
2050*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
2051*7c478bd9Sstevel@tonic-gate 
2052*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_ASTRING);
2053*7c478bd9Sstevel@tonic-gate 
2054*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
2055*7c478bd9Sstevel@tonic-gate 		return (NULL);
2056*7c478bd9Sstevel@tonic-gate 
2057*7c478bd9Sstevel@tonic-gate 	return (ret->pv_str);
2058*7c478bd9Sstevel@tonic-gate }
2059*7c478bd9Sstevel@tonic-gate 
2060*7c478bd9Sstevel@tonic-gate char *
2061*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_ustring(scf_simple_prop_t *prop)
2062*7c478bd9Sstevel@tonic-gate {
2063*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
2064*7c478bd9Sstevel@tonic-gate 
2065*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_USTRING);
2066*7c478bd9Sstevel@tonic-gate 
2067*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
2068*7c478bd9Sstevel@tonic-gate 		return (NULL);
2069*7c478bd9Sstevel@tonic-gate 
2070*7c478bd9Sstevel@tonic-gate 	return (ret->pv_str);
2071*7c478bd9Sstevel@tonic-gate }
2072*7c478bd9Sstevel@tonic-gate 
2073*7c478bd9Sstevel@tonic-gate void *
2074*7c478bd9Sstevel@tonic-gate scf_simple_prop_next_opaque(scf_simple_prop_t *prop, size_t *length)
2075*7c478bd9Sstevel@tonic-gate {
2076*7c478bd9Sstevel@tonic-gate 	union scf_simple_prop_val *ret;
2077*7c478bd9Sstevel@tonic-gate 
2078*7c478bd9Sstevel@tonic-gate 	ret = scf_next_val(prop, SCF_TYPE_OPAQUE);
2079*7c478bd9Sstevel@tonic-gate 
2080*7c478bd9Sstevel@tonic-gate 	if (ret == NULL) {
2081*7c478bd9Sstevel@tonic-gate 		*length = 0;
2082*7c478bd9Sstevel@tonic-gate 		return (NULL);
2083*7c478bd9Sstevel@tonic-gate 	}
2084*7c478bd9Sstevel@tonic-gate 
2085*7c478bd9Sstevel@tonic-gate 	*length = ret->pv_opaque.o_size;
2086*7c478bd9Sstevel@tonic-gate 	return (ret->pv_opaque.o_value);
2087*7c478bd9Sstevel@tonic-gate }
2088