17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53eae19d9Swesolows  * Common Development and Distribution License (the "License").
63eae19d9Swesolows  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
213eae19d9Swesolows 
227c478bd9Sstevel@tonic-gate /*
23*f329b923SSean Wilcox  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <assert.h>
277c478bd9Sstevel@tonic-gate #include <errno.h>
287c478bd9Sstevel@tonic-gate #include <libintl.h>
297c478bd9Sstevel@tonic-gate #include <libuutil.h>
307c478bd9Sstevel@tonic-gate #include <stdarg.h>
317c478bd9Sstevel@tonic-gate #include <stddef.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
331f6eb021SLiane Praza #include <unistd.h>
341f6eb021SLiane Praza #include <libscf_priv.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include "svccfg.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Internal representation manipulation routines for svccfg(1)
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate static uu_list_pool_t	*entity_pool;
437c478bd9Sstevel@tonic-gate static uu_list_pool_t	*pgroup_pool;
447c478bd9Sstevel@tonic-gate static uu_list_pool_t	*property_pool;
457c478bd9Sstevel@tonic-gate static uu_list_pool_t	*value_pool;
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /* ARGSUSED */
487c478bd9Sstevel@tonic-gate static int
entity_cmp(const void * a,const void * b,void * p)497c478bd9Sstevel@tonic-gate entity_cmp(const void *a, const void *b, void *p)
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate 	entity_t *A = (entity_t *)a;
527c478bd9Sstevel@tonic-gate 	entity_t *B = (entity_t *)b;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	return (strcmp(A->sc_name, B->sc_name));
557c478bd9Sstevel@tonic-gate }
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*ARGSUSED*/
587c478bd9Sstevel@tonic-gate static int
pgroup_cmp(const void * a,const void * b,void * p)597c478bd9Sstevel@tonic-gate pgroup_cmp(const void *a, const void *b, void *p)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate 	pgroup_t *A = (pgroup_t *)a;
627c478bd9Sstevel@tonic-gate 	pgroup_t *B = (pgroup_t *)b;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	return (strcmp(A->sc_pgroup_name, B->sc_pgroup_name));
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /* ARGSUSED */
687c478bd9Sstevel@tonic-gate static int
property_cmp(const void * a,const void * b,void * p)697c478bd9Sstevel@tonic-gate property_cmp(const void *a, const void *b, void *p)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate 	property_t *A = (property_t *)a;
727c478bd9Sstevel@tonic-gate 	property_t *B = (property_t *)b;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	return (strcmp(A->sc_property_name, B->sc_property_name));
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /* ARGSUSED */
787c478bd9Sstevel@tonic-gate int
value_cmp(const void * a,const void * b,void * p)797c478bd9Sstevel@tonic-gate value_cmp(const void *a, const void *b, void *p)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	const value_t *A = a;
827c478bd9Sstevel@tonic-gate 	const value_t *B = b;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (A->sc_type != B->sc_type)
857c478bd9Sstevel@tonic-gate 		return (B->sc_type - A->sc_type);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	switch (A->sc_type) {
887c478bd9Sstevel@tonic-gate 	case SCF_TYPE_BOOLEAN:
897c478bd9Sstevel@tonic-gate 	case SCF_TYPE_COUNT:
907c478bd9Sstevel@tonic-gate 		return (B->sc_u.sc_count - A->sc_u.sc_count);
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	case SCF_TYPE_INTEGER:
937c478bd9Sstevel@tonic-gate 		return (B->sc_u.sc_integer - A->sc_u.sc_integer);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	default:
967c478bd9Sstevel@tonic-gate 		return (strcmp(A->sc_u.sc_string, B->sc_u.sc_string));
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate void
internal_init()1017c478bd9Sstevel@tonic-gate internal_init()
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	if ((entity_pool = uu_list_pool_create("entities", sizeof (entity_t),
1047c478bd9Sstevel@tonic-gate 	    offsetof(entity_t, sc_node), entity_cmp, 0)) == NULL)
1057c478bd9Sstevel@tonic-gate 		uu_die(gettext("entity list pool creation failed: %s\n"),
1067c478bd9Sstevel@tonic-gate 		    uu_strerror(uu_error()));
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if ((pgroup_pool = uu_list_pool_create("property_groups",
1097c478bd9Sstevel@tonic-gate 	    sizeof (pgroup_t), offsetof(pgroup_t, sc_node), pgroup_cmp, 0)) ==
1107c478bd9Sstevel@tonic-gate 	    NULL)
1117c478bd9Sstevel@tonic-gate 		uu_die(
1127c478bd9Sstevel@tonic-gate 		    gettext("property group list pool creation failed: %s\n"),
1137c478bd9Sstevel@tonic-gate 		    uu_strerror(uu_error()));
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	if ((property_pool = uu_list_pool_create("properties",
1167c478bd9Sstevel@tonic-gate 	    sizeof (property_t), offsetof(property_t, sc_node), property_cmp,
1177c478bd9Sstevel@tonic-gate 	    0)) == NULL)
1187c478bd9Sstevel@tonic-gate 		uu_die(gettext("property list pool creation failed: %s\n"),
1197c478bd9Sstevel@tonic-gate 		    uu_strerror(uu_error()));
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	if ((value_pool = uu_list_pool_create("property_values",
1227c478bd9Sstevel@tonic-gate 	    sizeof (value_t), offsetof(value_t, sc_node), value_cmp, 0)) ==
1237c478bd9Sstevel@tonic-gate 	    NULL)
1247c478bd9Sstevel@tonic-gate 		uu_die(
1257c478bd9Sstevel@tonic-gate 		    gettext("property value list pool creation failed: %s\n"),
1267c478bd9Sstevel@tonic-gate 		    uu_strerror(uu_error()));
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1307c478bd9Sstevel@tonic-gate static int
internal_value_dump(void * v,void * pvt)1317c478bd9Sstevel@tonic-gate internal_value_dump(void *v, void *pvt)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	value_t *val = v;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	switch (val->sc_type) {
1367c478bd9Sstevel@tonic-gate 	case SCF_TYPE_BOOLEAN:
1377c478bd9Sstevel@tonic-gate 		(void) printf("	value = %s\n",
1387c478bd9Sstevel@tonic-gate 		    val->sc_u.sc_count ? "true" : "false");
1397c478bd9Sstevel@tonic-gate 		break;
1407c478bd9Sstevel@tonic-gate 	case SCF_TYPE_COUNT:
1417c478bd9Sstevel@tonic-gate 		(void) printf("	value = %llu\n", val->sc_u.sc_count);
1427c478bd9Sstevel@tonic-gate 		break;
1437c478bd9Sstevel@tonic-gate 	case SCF_TYPE_INTEGER:
1447c478bd9Sstevel@tonic-gate 		(void) printf("	value = %lld\n", val->sc_u.sc_integer);
1457c478bd9Sstevel@tonic-gate 		break;
1467c478bd9Sstevel@tonic-gate 	case SCF_TYPE_ASTRING:
1477c478bd9Sstevel@tonic-gate 	case SCF_TYPE_FMRI:
1487c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOST:
1497c478bd9Sstevel@tonic-gate 	case SCF_TYPE_HOSTNAME:
1507c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V4:
1517c478bd9Sstevel@tonic-gate 	case SCF_TYPE_NET_ADDR_V6:
1527c478bd9Sstevel@tonic-gate 	case SCF_TYPE_OPAQUE:
1537c478bd9Sstevel@tonic-gate 	case SCF_TYPE_TIME:
1547c478bd9Sstevel@tonic-gate 	case SCF_TYPE_URI:
1557c478bd9Sstevel@tonic-gate 	case SCF_TYPE_USTRING:
1567c478bd9Sstevel@tonic-gate 		(void) printf("	value = %s\n",
1577c478bd9Sstevel@tonic-gate 		    val->sc_u.sc_string ? val->sc_u.sc_string : "(nil)");
1587c478bd9Sstevel@tonic-gate 		break;
1597c478bd9Sstevel@tonic-gate 	default:
1607c478bd9Sstevel@tonic-gate 		uu_die(gettext("unknown value type (%d)\n"), val->sc_type);
1617c478bd9Sstevel@tonic-gate 		break;
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	return (UU_WALK_NEXT);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1687c478bd9Sstevel@tonic-gate static int
internal_property_dump(void * v,void * pvt)1697c478bd9Sstevel@tonic-gate internal_property_dump(void *v, void *pvt)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate 	property_t *p = v;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	(void) printf("property\n	name = %s\n", p->sc_property_name);
1747c478bd9Sstevel@tonic-gate 	(void) printf("	type = %d\n", p->sc_value_type);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	(void) uu_list_walk(p->sc_property_values, internal_value_dump,
1777c478bd9Sstevel@tonic-gate 	    NULL, UU_DEFAULT);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	return (UU_WALK_NEXT);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1837c478bd9Sstevel@tonic-gate static int
internal_pgroup_dump(void * v,void * pvt)1847c478bd9Sstevel@tonic-gate internal_pgroup_dump(void *v, void *pvt)
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate 	pgroup_t *pg = v;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	(void) printf("pgroup	name = %s\n", pg->sc_pgroup_name);
1897c478bd9Sstevel@tonic-gate 	(void) printf("	type = %s\n", pg->sc_pgroup_type);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	(void) uu_list_walk(pg->sc_pgroup_props, internal_property_dump,
1927c478bd9Sstevel@tonic-gate 	    NULL, UU_DEFAULT);
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	return (UU_WALK_NEXT);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1987c478bd9Sstevel@tonic-gate static int
internal_instance_dump(void * v,void * pvt)1997c478bd9Sstevel@tonic-gate internal_instance_dump(void *v, void *pvt)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	entity_t *i = v;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	(void) printf("instance	name = %s\n", i->sc_name);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	(void) uu_list_walk(i->sc_pgroups, internal_pgroup_dump, NULL,
2067c478bd9Sstevel@tonic-gate 	    UU_DEFAULT);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	return (UU_WALK_NEXT);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2127c478bd9Sstevel@tonic-gate static int
internal_service_dump(void * v,void * pvt)2137c478bd9Sstevel@tonic-gate internal_service_dump(void *v, void *pvt)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	entity_t *s = v;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	(void) printf("service	name = %s\n", s->sc_name);
2187c478bd9Sstevel@tonic-gate 	(void) printf("	type = %x\n", s->sc_u.sc_service.sc_service_type);
2197c478bd9Sstevel@tonic-gate 	(void) printf("	version = %u\n", s->sc_u.sc_service.sc_service_version);
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	(void) uu_list_walk(s->sc_pgroups, internal_pgroup_dump, NULL,
2227c478bd9Sstevel@tonic-gate 	    UU_DEFAULT);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	(void) uu_list_walk(s->sc_u.sc_service.sc_service_instances,
2257c478bd9Sstevel@tonic-gate 	    internal_instance_dump, NULL, UU_DEFAULT);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	return (UU_WALK_NEXT);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate void
internal_dump(bundle_t * b)2317c478bd9Sstevel@tonic-gate internal_dump(bundle_t *b)
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate 	(void) printf("bundle	name = %s\n", b->sc_bundle_name);
2347c478bd9Sstevel@tonic-gate 	(void) printf("	type = %x\n", b->sc_bundle_type);
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	(void) uu_list_walk(b->sc_bundle_services, internal_service_dump,
2377c478bd9Sstevel@tonic-gate 	    NULL, UU_DEFAULT);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate bundle_t *
internal_bundle_new()2417c478bd9Sstevel@tonic-gate internal_bundle_new()
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	bundle_t	*b;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if ((b = uu_zalloc(sizeof (bundle_t))) == NULL)
2467c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	b->sc_bundle_type = SVCCFG_UNKNOWN_BUNDLE;
2497c478bd9Sstevel@tonic-gate 	b->sc_bundle_services = uu_list_create(entity_pool, b, 0);
2501f6eb021SLiane Praza 	if (b->sc_bundle_services == NULL) {
2511f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for bundle services.  "
2521f6eb021SLiane Praza 		    "%s\n"), uu_strerror(uu_error()));
2531f6eb021SLiane Praza 	}
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	return (b);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate void
internal_bundle_free(bundle_t * b)2597c478bd9Sstevel@tonic-gate internal_bundle_free(bundle_t *b)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate 	void *cookie = NULL;
2627c478bd9Sstevel@tonic-gate 	entity_t *service;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	while ((service = uu_list_teardown(b->sc_bundle_services, &cookie)) !=
2657c478bd9Sstevel@tonic-gate 	    NULL)
2667c478bd9Sstevel@tonic-gate 		internal_service_free(service);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	free(b);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate entity_t *
internal_entity_new(entity_type_t entity)2721f6eb021SLiane Praza internal_entity_new(entity_type_t entity)
2737c478bd9Sstevel@tonic-gate {
2741f6eb021SLiane Praza 	entity_t *e;
2757c478bd9Sstevel@tonic-gate 
2761f6eb021SLiane Praza 	if ((e = uu_zalloc(sizeof (entity_t))) == NULL)
2777c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
2787c478bd9Sstevel@tonic-gate 
2791f6eb021SLiane Praza 	uu_list_node_init(e, &e->sc_node, entity_pool);
2801f6eb021SLiane Praza 
2811f6eb021SLiane Praza 	e->sc_etype = entity;
2821f6eb021SLiane Praza 	e->sc_pgroups = uu_list_create(pgroup_pool, e, 0);
283*f329b923SSean Wilcox 	e->sc_op = SVCCFG_OP_NONE;
2841f6eb021SLiane Praza 	if (e->sc_pgroups == NULL) {
2851f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for entity property "
2861f6eb021SLiane Praza 		    "groups.  %s\n"), uu_strerror(uu_error()));
2871f6eb021SLiane Praza 	}
2881f6eb021SLiane Praza 
2891f6eb021SLiane Praza 	return (e);
2901f6eb021SLiane Praza }
2911f6eb021SLiane Praza 
2921f6eb021SLiane Praza entity_t *
internal_service_new(const char * name)2931f6eb021SLiane Praza internal_service_new(const char *name)
2941f6eb021SLiane Praza {
2951f6eb021SLiane Praza 	entity_t *s;
2961f6eb021SLiane Praza 
2971f6eb021SLiane Praza 	s = internal_entity_new(SVCCFG_SERVICE_OBJECT);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	s->sc_name = name;
3007c478bd9Sstevel@tonic-gate 	s->sc_fmri = uu_msprintf("svc:/%s", name);
3017c478bd9Sstevel@tonic-gate 	if (s->sc_fmri == NULL)
3027c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	s->sc_dependents = uu_list_create(pgroup_pool, s, 0);
3051f6eb021SLiane Praza 	if (s->sc_dependents == NULL) {
3061f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for service dependents.  "
3071f6eb021SLiane Praza 		    "%s\n"), uu_strerror(uu_error()));
3081f6eb021SLiane Praza 	}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	s->sc_u.sc_service.sc_service_type = SVCCFG_UNKNOWN_SERVICE;
3117c478bd9Sstevel@tonic-gate 	s->sc_u.sc_service.sc_service_instances = uu_list_create(entity_pool, s,
3127c478bd9Sstevel@tonic-gate 	    0);
3131f6eb021SLiane Praza 	if (s->sc_u.sc_service.sc_service_instances == NULL) {
3141f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for service instances.  "
3151f6eb021SLiane Praza 		    "%s\n"), uu_strerror(uu_error()));
3161f6eb021SLiane Praza 	}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	return (s);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate void
internal_service_free(entity_t * s)3227c478bd9Sstevel@tonic-gate internal_service_free(entity_t *s)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	entity_t *inst;
3257c478bd9Sstevel@tonic-gate 	pgroup_t *pg;
3267c478bd9Sstevel@tonic-gate 	void *cookie;
3277c478bd9Sstevel@tonic-gate 
3281f6eb021SLiane Praza 	if (s->sc_u.sc_service.sc_restarter != NULL)
3291f6eb021SLiane Praza 		internal_instance_free(s->sc_u.sc_service.sc_restarter);
3301f6eb021SLiane Praza 	if (s->sc_u.sc_service.sc_global != NULL)
3311f6eb021SLiane Praza 		internal_instance_free(s->sc_u.sc_service.sc_global);
3321f6eb021SLiane Praza 
3337c478bd9Sstevel@tonic-gate 	cookie = NULL;
3347c478bd9Sstevel@tonic-gate 	while ((pg = uu_list_teardown(s->sc_pgroups, &cookie)) != NULL)
3357c478bd9Sstevel@tonic-gate 		internal_pgroup_free(pg);
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	cookie = NULL;
3387c478bd9Sstevel@tonic-gate 	while ((pg = uu_list_teardown(s->sc_dependents, &cookie)) != NULL)
3397c478bd9Sstevel@tonic-gate 		internal_pgroup_free(pg);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	cookie = NULL;
3427c478bd9Sstevel@tonic-gate 	while ((inst = uu_list_teardown(s->sc_u.sc_service.sc_service_instances,
3437c478bd9Sstevel@tonic-gate 	    &cookie)) != NULL)
3447c478bd9Sstevel@tonic-gate 		internal_instance_free(inst);
3451f6eb021SLiane Praza 	uu_free((void *)s->sc_fmri);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	free(s);
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate entity_t *
internal_instance_new(const char * name)3517c478bd9Sstevel@tonic-gate internal_instance_new(const char *name)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate 	entity_t *i;
3547c478bd9Sstevel@tonic-gate 
3551f6eb021SLiane Praza 	i = internal_entity_new(SVCCFG_INSTANCE_OBJECT);
3567c478bd9Sstevel@tonic-gate 	i->sc_name = name;
3577c478bd9Sstevel@tonic-gate 	/* Can't set i->sc_fmri until we're attached to a service. */
3587c478bd9Sstevel@tonic-gate 	i->sc_dependents = uu_list_create(pgroup_pool, i, 0);
3591f6eb021SLiane Praza 	if (i->sc_dependents == NULL) {
3601f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for instance "
3611f6eb021SLiane Praza 		    "dependents.  %s\n"), uu_strerror(uu_error()));
3621f6eb021SLiane Praza 	}
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	return (i);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate void
internal_instance_free(entity_t * i)3687c478bd9Sstevel@tonic-gate internal_instance_free(entity_t *i)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate 	pgroup_t *pg;
3717c478bd9Sstevel@tonic-gate 	void *cookie = NULL;
3721f6eb021SLiane Praza 	entity_t *rs;
3737c478bd9Sstevel@tonic-gate 
3741f6eb021SLiane Praza 	rs = i->sc_u.sc_instance.sc_instance_restarter;
3751f6eb021SLiane Praza 	if (rs != NULL)
3761f6eb021SLiane Praza 		internal_instance_free(rs);
3777c478bd9Sstevel@tonic-gate 	while ((pg = uu_list_teardown(i->sc_pgroups, &cookie)) != NULL)
3787c478bd9Sstevel@tonic-gate 		internal_pgroup_free(pg);
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	cookie = NULL;
3817c478bd9Sstevel@tonic-gate 	while ((pg = uu_list_teardown(i->sc_dependents, &cookie)) != NULL)
3827c478bd9Sstevel@tonic-gate 		internal_pgroup_free(pg);
3831f6eb021SLiane Praza 	uu_free((void *)i->sc_fmri);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	free(i);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate pgroup_t *
internal_pgroup_new()3897c478bd9Sstevel@tonic-gate internal_pgroup_new()
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	pgroup_t *p;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	if ((p = uu_zalloc(sizeof (pgroup_t))) == NULL)
3947c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	uu_list_node_init(p, &p->sc_node, pgroup_pool);
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	p->sc_pgroup_props = uu_list_create(property_pool, p, UU_LIST_SORTED);
3991f6eb021SLiane Praza 	if (p->sc_pgroup_props == NULL) {
4001f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for properties.  %s\n"),
4011f6eb021SLiane Praza 		    uu_strerror(uu_error()));
4021f6eb021SLiane Praza 	}
4037c478bd9Sstevel@tonic-gate 	p->sc_pgroup_name = "<unset>";
4047c478bd9Sstevel@tonic-gate 	p->sc_pgroup_type = "<unset>";
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	return (p);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate void
internal_pgroup_free(pgroup_t * pg)4107c478bd9Sstevel@tonic-gate internal_pgroup_free(pgroup_t *pg)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	property_t *prop;
4137c478bd9Sstevel@tonic-gate 	void *cookie = NULL;
4147c478bd9Sstevel@tonic-gate 
4151f6eb021SLiane Praza 	/*
4161f6eb021SLiane Praza 	 * Templates validation code should clean up this reference when
4171f6eb021SLiane Praza 	 * the validation is finished.
4181f6eb021SLiane Praza 	 */
4191f6eb021SLiane Praza 	assert(pg->sc_pgroup_composed == NULL);
4201f6eb021SLiane Praza 
4217c478bd9Sstevel@tonic-gate 	while ((prop = uu_list_teardown(pg->sc_pgroup_props, &cookie)) != NULL)
4227c478bd9Sstevel@tonic-gate 		internal_property_free(prop);
4237c478bd9Sstevel@tonic-gate 
4249e9ae1fcSbustos 	uu_free(pg);
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate static pgroup_t *
find_pgroup(uu_list_t * list,const char * name,const char * type)4287c478bd9Sstevel@tonic-gate find_pgroup(uu_list_t *list, const char *name, const char *type)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate 	pgroup_t *pg;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	for (pg = uu_list_first(list);
4337c478bd9Sstevel@tonic-gate 	    pg != NULL;
4347c478bd9Sstevel@tonic-gate 	    pg = uu_list_next(list, pg)) {
4357c478bd9Sstevel@tonic-gate 		if (strcmp(pg->sc_pgroup_name, name) != 0)
4367c478bd9Sstevel@tonic-gate 			continue;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 		if (type == NULL)
4397c478bd9Sstevel@tonic-gate 			return (pg);
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 		if (strcmp(pg->sc_pgroup_type, type) == 0)
4427c478bd9Sstevel@tonic-gate 			return (pg);
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	return (NULL);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate pgroup_t *
internal_dependent_find(entity_t * e,const char * name)4497c478bd9Sstevel@tonic-gate internal_dependent_find(entity_t *e, const char *name)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 	return (find_pgroup(e->sc_dependents, name, NULL));
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate pgroup_t *
internal_pgroup_find(entity_t * e,const char * name,const char * type)4557c478bd9Sstevel@tonic-gate internal_pgroup_find(entity_t *e, const char *name, const char *type)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	return (find_pgroup(e->sc_pgroups, name, type));
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4601f6eb021SLiane Praza static pgroup_t *
internal_pgroup_create_common(entity_t * e,const char * name,const char * type,boolean_t unique)4611f6eb021SLiane Praza internal_pgroup_create_common(entity_t *e, const char *name, const char *type,
4621f6eb021SLiane Praza 	boolean_t unique)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	pgroup_t *pg;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	pg = internal_pgroup_find(e, name, type);
4671f6eb021SLiane Praza 	if (pg != NULL) {
4681f6eb021SLiane Praza 		if (unique == B_TRUE) {
4691f6eb021SLiane Praza 			return (NULL);
4701f6eb021SLiane Praza 		} else {
4711f6eb021SLiane Praza 			return (pg);
4721f6eb021SLiane Praza 		}
4731f6eb021SLiane Praza 	}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	pg = internal_pgroup_new();
4767c478bd9Sstevel@tonic-gate 	(void) internal_attach_pgroup(e, pg);
4777c478bd9Sstevel@tonic-gate 	pg->sc_pgroup_name = strdup(name);
4787c478bd9Sstevel@tonic-gate 	pg->sc_pgroup_flags = 0;
479*f329b923SSean Wilcox 	if (type != NULL) {
480*f329b923SSean Wilcox 		pg->sc_pgroup_type = strdup(type);
481*f329b923SSean Wilcox 	} else {
482*f329b923SSean Wilcox 		est->sc_miss_type = B_TRUE;
483*f329b923SSean Wilcox 		pg->sc_pgroup_type = NULL;
484*f329b923SSean Wilcox 	}
4857c478bd9Sstevel@tonic-gate 
486*f329b923SSean Wilcox 	if (pg->sc_pgroup_name == NULL ||
487*f329b923SSean Wilcox 	    (e->sc_op != SVCCFG_OP_APPLY && pg->sc_pgroup_type == NULL))
4887c478bd9Sstevel@tonic-gate 		uu_die(gettext("Could not duplicate string"));
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	return (pg);
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4931f6eb021SLiane Praza pgroup_t *
internal_pgroup_find_or_create(entity_t * e,const char * name,const char * type)4941f6eb021SLiane Praza internal_pgroup_find_or_create(entity_t *e, const char *name, const char *type)
4951f6eb021SLiane Praza {
4961f6eb021SLiane Praza 	return (internal_pgroup_create_common(e, name, type, B_FALSE));
4971f6eb021SLiane Praza }
4981f6eb021SLiane Praza 
4991f6eb021SLiane Praza pgroup_t *
internal_pgroup_create_strict(entity_t * e,const char * name,const char * type)5001f6eb021SLiane Praza internal_pgroup_create_strict(entity_t *e, const char *name, const char *type)
5011f6eb021SLiane Praza {
5021f6eb021SLiane Praza 	return (internal_pgroup_create_common(e, name, type, B_TRUE));
5031f6eb021SLiane Praza }
5041f6eb021SLiane Praza 
5057c478bd9Sstevel@tonic-gate property_t *
internal_property_new()5067c478bd9Sstevel@tonic-gate internal_property_new()
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	property_t *p;
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	if ((p = uu_zalloc(sizeof (property_t))) == NULL)
5117c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	uu_list_node_init(p, &p->sc_node, property_pool);
5147c478bd9Sstevel@tonic-gate 
5156e1d2b42Samaguire 	p->sc_property_values = uu_list_create(value_pool, p, 0);
5161f6eb021SLiane Praza 	if (p->sc_property_values == NULL) {
5171f6eb021SLiane Praza 		uu_die(gettext("Unable to create list for property values.  "
5181f6eb021SLiane Praza 		    "%s\n"), uu_strerror(uu_error()));
5191f6eb021SLiane Praza 	}
5207c478bd9Sstevel@tonic-gate 	p->sc_property_name = "<unset>";
5217c478bd9Sstevel@tonic-gate 
5221f6eb021SLiane Praza 	tmpl_property_init(p);
5231f6eb021SLiane Praza 
5247c478bd9Sstevel@tonic-gate 	return (p);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate void
internal_property_free(property_t * p)5287c478bd9Sstevel@tonic-gate internal_property_free(property_t *p)
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	value_t *val;
5317c478bd9Sstevel@tonic-gate 	void *cookie = NULL;
5327c478bd9Sstevel@tonic-gate 
5331f6eb021SLiane Praza 	tmpl_property_fini(p);
5341f6eb021SLiane Praza 
5357c478bd9Sstevel@tonic-gate 	while ((val = uu_list_teardown(p->sc_property_values, &cookie)) !=
5367c478bd9Sstevel@tonic-gate 	    NULL) {
5377c478bd9Sstevel@tonic-gate 		if (val->sc_free != NULL)
5387c478bd9Sstevel@tonic-gate 			val->sc_free(val);
5397c478bd9Sstevel@tonic-gate 		free(val);
5407c478bd9Sstevel@tonic-gate 	}
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	free(p);
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate property_t *
internal_property_find(pgroup_t * pg,const char * name)5467c478bd9Sstevel@tonic-gate internal_property_find(pgroup_t *pg, const char *name)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	property_t *p;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	for (p = uu_list_first(pg->sc_pgroup_props);
5517c478bd9Sstevel@tonic-gate 	    p != NULL;
5527c478bd9Sstevel@tonic-gate 	    p = uu_list_next(pg->sc_pgroup_props, p))
5537c478bd9Sstevel@tonic-gate 		if (strcmp(p->sc_property_name, name) == 0)
5547c478bd9Sstevel@tonic-gate 			return (p);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	return (NULL);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate value_t *
internal_value_new()5607c478bd9Sstevel@tonic-gate internal_value_new()
5617c478bd9Sstevel@tonic-gate {
5627c478bd9Sstevel@tonic-gate 	value_t *v;
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	if ((v = uu_zalloc(sizeof (value_t))) == NULL)
5657c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	uu_list_node_init(v, &v->sc_node, value_pool);
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	return (v);
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate static void
internal_value_free_str(value_t * v)5737c478bd9Sstevel@tonic-gate internal_value_free_str(value_t *v)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	free(v->sc_u.sc_string);
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate property_t *
internal_property_create(const char * name,scf_type_t vtype,uint_t nvals,...)5797c478bd9Sstevel@tonic-gate internal_property_create(const char *name, scf_type_t vtype, uint_t nvals, ...)
5807c478bd9Sstevel@tonic-gate {
5817c478bd9Sstevel@tonic-gate 	va_list args;
5827c478bd9Sstevel@tonic-gate 	property_t *p;
5837c478bd9Sstevel@tonic-gate 	value_t *v;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	p = internal_property_new();
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	p->sc_property_name = (char *)name;
5887c478bd9Sstevel@tonic-gate 	p->sc_value_type = vtype;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	va_start(args, nvals);
5917c478bd9Sstevel@tonic-gate 	for (; nvals > 0; nvals--) {
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 		v = internal_value_new();
5947c478bd9Sstevel@tonic-gate 		v->sc_type = vtype;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		switch (vtype) {
5977c478bd9Sstevel@tonic-gate 		case SCF_TYPE_BOOLEAN:
5987c478bd9Sstevel@tonic-gate 		case SCF_TYPE_COUNT:
5997c478bd9Sstevel@tonic-gate 			v->sc_u.sc_count = va_arg(args, uint64_t);
6007c478bd9Sstevel@tonic-gate 			break;
6017c478bd9Sstevel@tonic-gate 		case SCF_TYPE_INTEGER:
6027c478bd9Sstevel@tonic-gate 			v->sc_u.sc_integer = va_arg(args, int64_t);
6037c478bd9Sstevel@tonic-gate 			break;
6047c478bd9Sstevel@tonic-gate 		case SCF_TYPE_ASTRING:
6057c478bd9Sstevel@tonic-gate 		case SCF_TYPE_FMRI:
6067c478bd9Sstevel@tonic-gate 		case SCF_TYPE_HOST:
6077c478bd9Sstevel@tonic-gate 		case SCF_TYPE_HOSTNAME:
6087c478bd9Sstevel@tonic-gate 		case SCF_TYPE_NET_ADDR_V4:
6097c478bd9Sstevel@tonic-gate 		case SCF_TYPE_NET_ADDR_V6:
6107c478bd9Sstevel@tonic-gate 		case SCF_TYPE_OPAQUE:
6117c478bd9Sstevel@tonic-gate 		case SCF_TYPE_TIME:
6127c478bd9Sstevel@tonic-gate 		case SCF_TYPE_URI:
6137c478bd9Sstevel@tonic-gate 		case SCF_TYPE_USTRING:
6147c478bd9Sstevel@tonic-gate 			v->sc_u.sc_string = (char *)va_arg(args, uchar_t *);
6157c478bd9Sstevel@tonic-gate 			break;
6167c478bd9Sstevel@tonic-gate 		default:
6177c478bd9Sstevel@tonic-gate 			va_end(args);
6187c478bd9Sstevel@tonic-gate 			uu_die(gettext("unknown property type (%d)\n"), vtype);
6197c478bd9Sstevel@tonic-gate 			break;
6207c478bd9Sstevel@tonic-gate 		}
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 		internal_attach_value(p, v);
6237c478bd9Sstevel@tonic-gate 	}
6247c478bd9Sstevel@tonic-gate 	va_end(args);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	return (p);
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate  * Some of these attach functions use uu_list_append() to maintain the
6317c478bd9Sstevel@tonic-gate  * same order across import/export, whereas others are always sorted
6327c478bd9Sstevel@tonic-gate  * anyway, or the order is irrelevant.
6337c478bd9Sstevel@tonic-gate  */
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate int
internal_attach_service(bundle_t * bndl,entity_t * svc)6367c478bd9Sstevel@tonic-gate internal_attach_service(bundle_t *bndl, entity_t *svc)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate 	if (uu_list_find(bndl->sc_bundle_services, svc, NULL, NULL) != NULL) {
6397c478bd9Sstevel@tonic-gate 		semerr(gettext("Multiple definitions for service %s in "
6407c478bd9Sstevel@tonic-gate 		    "bundle %s.\n"), svc->sc_name, bndl->sc_bundle_name);
6417c478bd9Sstevel@tonic-gate 		return (-1);
6427c478bd9Sstevel@tonic-gate 	}
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	(void) uu_list_append(bndl->sc_bundle_services, svc);
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	return (0);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate int
internal_attach_entity(entity_t * svc,entity_t * ent)6507c478bd9Sstevel@tonic-gate internal_attach_entity(entity_t *svc, entity_t *ent)
6517c478bd9Sstevel@tonic-gate {
6527c478bd9Sstevel@tonic-gate 	if (svc->sc_etype != SVCCFG_SERVICE_OBJECT)
6537c478bd9Sstevel@tonic-gate 		uu_die(gettext("bad entity attach: %s is not a service\n"),
6547c478bd9Sstevel@tonic-gate 		    svc->sc_name);
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	if (uu_list_find(svc->sc_u.sc_service.sc_service_instances, ent, NULL,
6577c478bd9Sstevel@tonic-gate 	    NULL) != NULL) {
6587c478bd9Sstevel@tonic-gate 		semerr(gettext("Multiple definitions of entity %s in service "
6597c478bd9Sstevel@tonic-gate 		    "%s.\n"), ent->sc_name, svc->sc_name);
6607c478bd9Sstevel@tonic-gate 		return (-1);
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	(void) uu_list_prepend(svc->sc_u.sc_service.sc_service_instances, ent);
6647c478bd9Sstevel@tonic-gate 	ent->sc_parent = svc;
665*f329b923SSean Wilcox 	ent->sc_op = svc->sc_op;
6667c478bd9Sstevel@tonic-gate 	ent->sc_fmri = uu_msprintf("%s:%s", svc->sc_fmri, ent->sc_name);
6677c478bd9Sstevel@tonic-gate 	if (ent->sc_fmri == NULL)
6687c478bd9Sstevel@tonic-gate 		uu_die(gettext("couldn't allocate memory"));
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	return (0);
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate int
internal_attach_pgroup(entity_t * ent,pgroup_t * pgrp)6747c478bd9Sstevel@tonic-gate internal_attach_pgroup(entity_t *ent, pgroup_t *pgrp)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate 	if (uu_list_find(ent->sc_pgroups, pgrp, NULL, NULL) != NULL) {
6777c478bd9Sstevel@tonic-gate 		semerr(gettext("Multiple definitions of property group %s in "
6787c478bd9Sstevel@tonic-gate 		    "entity %s.\n"), pgrp->sc_pgroup_name, ent->sc_name);
6797c478bd9Sstevel@tonic-gate 		return (-1);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	(void) uu_list_append(ent->sc_pgroups, pgrp);
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	pgrp->sc_parent = ent;
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	return (0);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6891f6eb021SLiane Praza void
internal_detach_pgroup(entity_t * ent,pgroup_t * pgrp)6901f6eb021SLiane Praza internal_detach_pgroup(entity_t *ent, pgroup_t *pgrp)
6911f6eb021SLiane Praza {
6921f6eb021SLiane Praza 	uu_list_remove(ent->sc_pgroups, pgrp);
6931f6eb021SLiane Praza }
6941f6eb021SLiane Praza 
6957c478bd9Sstevel@tonic-gate int
internal_attach_dependent(entity_t * ent,pgroup_t * pg)6967c478bd9Sstevel@tonic-gate internal_attach_dependent(entity_t *ent, pgroup_t *pg)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate 	if (uu_list_find(ent->sc_dependents, pg, NULL, NULL) != NULL) {
6997c478bd9Sstevel@tonic-gate 		semerr(gettext("Multiple definitions of dependent %s in "
7007c478bd9Sstevel@tonic-gate 		    "entity %s.\n"), pg->sc_pgroup_name, ent->sc_name);
7017c478bd9Sstevel@tonic-gate 		return (-1);
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	(void) uu_list_append(ent->sc_dependents, pg);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	pg->sc_parent = ent;
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	return (0);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate /*
7127c478bd9Sstevel@tonic-gate  * Returns
7137c478bd9Sstevel@tonic-gate  *   0 - success
7147c478bd9Sstevel@tonic-gate  *   -1 - prop already exists in pgrp
7157c478bd9Sstevel@tonic-gate  */
7167c478bd9Sstevel@tonic-gate int
internal_attach_property(pgroup_t * pgrp,property_t * prop)7177c478bd9Sstevel@tonic-gate internal_attach_property(pgroup_t *pgrp, property_t *prop)
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate 	uu_list_index_t idx;
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	if (uu_list_find(pgrp->sc_pgroup_props, prop, NULL, &idx) != NULL) {
7227c478bd9Sstevel@tonic-gate 		semerr(gettext("Multiple definitions for property %s in "
7237c478bd9Sstevel@tonic-gate 		    "property group %s.\n"), prop->sc_property_name,
7247c478bd9Sstevel@tonic-gate 		    pgrp->sc_pgroup_name);
7257c478bd9Sstevel@tonic-gate 		return (-1);
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	uu_list_insert(pgrp->sc_pgroup_props, prop, idx);
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	return (0);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7331f6eb021SLiane Praza void
internal_detach_property(pgroup_t * pgrp,property_t * prop)7341f6eb021SLiane Praza internal_detach_property(pgroup_t *pgrp, property_t *prop)
7351f6eb021SLiane Praza {
7361f6eb021SLiane Praza 	uu_list_remove(pgrp->sc_pgroup_props, prop);
7371f6eb021SLiane Praza }
7381f6eb021SLiane Praza 
7397c478bd9Sstevel@tonic-gate void
internal_attach_value(property_t * prop,value_t * val)7407c478bd9Sstevel@tonic-gate internal_attach_value(property_t *prop, value_t *val)
7417c478bd9Sstevel@tonic-gate {
7426e1d2b42Samaguire 	(void) uu_list_append(prop->sc_property_values, val);
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate /*
7467c478bd9Sstevel@tonic-gate  * These functions create an internal representation of a property group
7477c478bd9Sstevel@tonic-gate  * (pgroup_t) from the repository (scf_propertygroup_t).  They are used by the
7487c478bd9Sstevel@tonic-gate  * import functions in svccfg_libscf.c .
7497c478bd9Sstevel@tonic-gate  *
7507c478bd9Sstevel@tonic-gate  * load_init() must be called first to initialize these globals, and
7517c478bd9Sstevel@tonic-gate  * load_fini() should be called afterwards to destroy them.
7527c478bd9Sstevel@tonic-gate  */
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate static char *loadbuf = NULL;
7557c478bd9Sstevel@tonic-gate static size_t loadbuf_sz;
7561f6eb021SLiane Praza static scf_propertygroup_t *load_pgroup = NULL;
7577c478bd9Sstevel@tonic-gate static scf_property_t *load_prop = NULL;
7587c478bd9Sstevel@tonic-gate static scf_value_t *load_val = NULL;
7597c478bd9Sstevel@tonic-gate static scf_iter_t *load_propiter = NULL, *load_valiter = NULL;
7601f6eb021SLiane Praza static scf_iter_t *load_pgiter = NULL;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate /*
7637c478bd9Sstevel@tonic-gate  * Initialize the global state for the load_*() routines.
7647c478bd9Sstevel@tonic-gate  * Returns
7657c478bd9Sstevel@tonic-gate  *   0 - success
7667c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
7677c478bd9Sstevel@tonic-gate  */
7687c478bd9Sstevel@tonic-gate int
load_init(void)7697c478bd9Sstevel@tonic-gate load_init(void)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	loadbuf_sz = ((max_scf_value_len > max_scf_pg_type_len) ?
7727c478bd9Sstevel@tonic-gate 	    max_scf_value_len : max_scf_pg_type_len) + 1;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	loadbuf = malloc(loadbuf_sz);
7757c478bd9Sstevel@tonic-gate 	if (loadbuf == NULL)
7767c478bd9Sstevel@tonic-gate 		return (ENOMEM);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	if ((load_prop = scf_property_create(g_hndl)) == NULL ||
7797c478bd9Sstevel@tonic-gate 	    (load_val = scf_value_create(g_hndl)) == NULL ||
7801f6eb021SLiane Praza 	    (load_pgroup = scf_pg_create(g_hndl)) == NULL ||
7811f6eb021SLiane Praza 	    (load_pgiter = scf_iter_create(g_hndl)) == NULL ||
7827c478bd9Sstevel@tonic-gate 	    (load_propiter = scf_iter_create(g_hndl)) == NULL ||
7837c478bd9Sstevel@tonic-gate 	    (load_valiter = scf_iter_create(g_hndl)) == NULL) {
7847c478bd9Sstevel@tonic-gate 		load_fini();
7857c478bd9Sstevel@tonic-gate 		return (ENOMEM);
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	return (0);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate void
load_fini(void)7927c478bd9Sstevel@tonic-gate load_fini(void)
7937c478bd9Sstevel@tonic-gate {
7947c478bd9Sstevel@tonic-gate 	scf_iter_destroy(load_propiter);
7957c478bd9Sstevel@tonic-gate 	load_propiter = NULL;
7967c478bd9Sstevel@tonic-gate 	scf_iter_destroy(load_valiter);
7977c478bd9Sstevel@tonic-gate 	load_valiter = NULL;
7981f6eb021SLiane Praza 	scf_iter_destroy(load_pgiter);
7991f6eb021SLiane Praza 	load_pgiter = NULL;
8001f6eb021SLiane Praza 	scf_pg_destroy(load_pgroup);
8011f6eb021SLiane Praza 	load_pgroup = NULL;
8027c478bd9Sstevel@tonic-gate 	scf_value_destroy(load_val);
8037c478bd9Sstevel@tonic-gate 	load_val = NULL;
8047c478bd9Sstevel@tonic-gate 	scf_property_destroy(load_prop);
8057c478bd9Sstevel@tonic-gate 	load_prop = NULL;
8067c478bd9Sstevel@tonic-gate 	free(loadbuf);
8077c478bd9Sstevel@tonic-gate 	loadbuf = NULL;
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate /*
8117c478bd9Sstevel@tonic-gate  * Create a property_t which represents an scf_property_t.  Returns
8127c478bd9Sstevel@tonic-gate  *   0 - success
8137c478bd9Sstevel@tonic-gate  *   ECANCELED - prop's pg was deleted
8147c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository disconnected
8157c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
8163eae19d9Swesolows  *   EACCES - permission denied when reading property
8177c478bd9Sstevel@tonic-gate  */
8187c478bd9Sstevel@tonic-gate static int
load_property(scf_property_t * prop,property_t ** ipp)8197c478bd9Sstevel@tonic-gate load_property(scf_property_t *prop, property_t **ipp)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate 	property_t *iprop;
8227c478bd9Sstevel@tonic-gate 	int r;
8237c478bd9Sstevel@tonic-gate 	ssize_t ssz;
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	/* get name */
8267c478bd9Sstevel@tonic-gate 	if (scf_property_get_name(prop, loadbuf, loadbuf_sz) < 0) {
8277c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
8287c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
8297c478bd9Sstevel@tonic-gate 			return (ECANCELED);
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
8327c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
8357c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
8367c478bd9Sstevel@tonic-gate 		default:
8377c478bd9Sstevel@tonic-gate 			bad_error("scf_property_get_name", scf_error());
8387c478bd9Sstevel@tonic-gate 		}
8397c478bd9Sstevel@tonic-gate 	}
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	iprop = internal_property_new();
8427c478bd9Sstevel@tonic-gate 	iprop->sc_property_name = strdup(loadbuf);
8437c478bd9Sstevel@tonic-gate 	if (iprop->sc_property_name == NULL) {
8447c478bd9Sstevel@tonic-gate 		internal_property_free(iprop);
8457c478bd9Sstevel@tonic-gate 		return (ENOMEM);
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	/* get type */
8497c478bd9Sstevel@tonic-gate 	if (scf_property_type(prop, &iprop->sc_value_type) != 0) {
8507c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
8517c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
8527c478bd9Sstevel@tonic-gate 			r = ECANCELED;
8537c478bd9Sstevel@tonic-gate 			goto out;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
8567c478bd9Sstevel@tonic-gate 			r = ECONNABORTED;
8577c478bd9Sstevel@tonic-gate 			goto out;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
8607c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
8617c478bd9Sstevel@tonic-gate 		default:
8627c478bd9Sstevel@tonic-gate 			bad_error("scf_property_type", scf_error());
8637c478bd9Sstevel@tonic-gate 		}
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	/* get values */
8677c478bd9Sstevel@tonic-gate 	if (scf_iter_property_values(load_valiter, prop) != 0) {
8687c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
8697c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
8707c478bd9Sstevel@tonic-gate 			r = ECANCELED;
8717c478bd9Sstevel@tonic-gate 			goto out;
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
8747c478bd9Sstevel@tonic-gate 			r = ECONNABORTED;
8757c478bd9Sstevel@tonic-gate 			goto out;
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
8787c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
8797c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
8807c478bd9Sstevel@tonic-gate 		default:
8817c478bd9Sstevel@tonic-gate 			bad_error("scf_iter_property_values", scf_error());
8827c478bd9Sstevel@tonic-gate 		}
8837c478bd9Sstevel@tonic-gate 	}
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	for (;;) {
8867c478bd9Sstevel@tonic-gate 		value_t *ival;
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 		r = scf_iter_next_value(load_valiter, load_val);
8897c478bd9Sstevel@tonic-gate 		if (r == 0)
8907c478bd9Sstevel@tonic-gate 			break;
8917c478bd9Sstevel@tonic-gate 		if (r != 1) {
8927c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
8937c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
8947c478bd9Sstevel@tonic-gate 				r = ECANCELED;
8957c478bd9Sstevel@tonic-gate 				goto out;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
8987c478bd9Sstevel@tonic-gate 				r = ECONNABORTED;
8997c478bd9Sstevel@tonic-gate 				goto out;
9007c478bd9Sstevel@tonic-gate 
9013eae19d9Swesolows 			case SCF_ERROR_PERMISSION_DENIED:
9023eae19d9Swesolows 				r = EACCES;
9033eae19d9Swesolows 				goto out;
9043eae19d9Swesolows 
9057c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
9067c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
9077c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
9087c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
9097c478bd9Sstevel@tonic-gate 			default:
9107c478bd9Sstevel@tonic-gate 				bad_error("scf_iter_next_value", scf_error());
9117c478bd9Sstevel@tonic-gate 			}
9127c478bd9Sstevel@tonic-gate 		}
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 		ival = internal_value_new();
9157c478bd9Sstevel@tonic-gate 		ival->sc_type = scf_value_type(load_val);
9167c478bd9Sstevel@tonic-gate 		assert(ival->sc_type != SCF_TYPE_INVALID);
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 		switch (ival->sc_type) {
9197c478bd9Sstevel@tonic-gate 		case SCF_TYPE_BOOLEAN: {
9207c478bd9Sstevel@tonic-gate 			uint8_t b;
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 			r = scf_value_get_boolean(load_val, &b);
9237c478bd9Sstevel@tonic-gate 			if (r != 0)
9247c478bd9Sstevel@tonic-gate 				bad_error("scf_value_get_boolean", scf_error());
9257c478bd9Sstevel@tonic-gate 			ival->sc_u.sc_count = b;
9267c478bd9Sstevel@tonic-gate 			break;
9277c478bd9Sstevel@tonic-gate 		}
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 		case SCF_TYPE_COUNT:
9307c478bd9Sstevel@tonic-gate 			r = scf_value_get_count(load_val, &ival->sc_u.sc_count);
9317c478bd9Sstevel@tonic-gate 			if (r != 0)
9327c478bd9Sstevel@tonic-gate 				bad_error("scf_value_get_count", scf_error());
9337c478bd9Sstevel@tonic-gate 			break;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 		case SCF_TYPE_INTEGER:
9367c478bd9Sstevel@tonic-gate 			r = scf_value_get_integer(load_val,
9377c478bd9Sstevel@tonic-gate 			    &ival->sc_u.sc_integer);
9387c478bd9Sstevel@tonic-gate 			if (r != 0)
9397c478bd9Sstevel@tonic-gate 				bad_error("scf_value_get_integer", scf_error());
9407c478bd9Sstevel@tonic-gate 			break;
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 		default:
9437c478bd9Sstevel@tonic-gate 			ssz = scf_value_get_as_string(load_val, loadbuf,
9447c478bd9Sstevel@tonic-gate 			    loadbuf_sz);
9457c478bd9Sstevel@tonic-gate 			if (ssz < 0)
9467c478bd9Sstevel@tonic-gate 				bad_error("scf_value_get_as_string",
9477c478bd9Sstevel@tonic-gate 				    scf_error());
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 			ival->sc_u.sc_string = strdup(loadbuf);
9507c478bd9Sstevel@tonic-gate 			if (ival->sc_u.sc_string == NULL) {
9517c478bd9Sstevel@tonic-gate 				r = ENOMEM;
9527c478bd9Sstevel@tonic-gate 				goto out;
9537c478bd9Sstevel@tonic-gate 			}
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 			ival->sc_free = internal_value_free_str;
9567c478bd9Sstevel@tonic-gate 		}
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 		internal_attach_value(iprop, ival);
9597c478bd9Sstevel@tonic-gate 	}
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	*ipp = iprop;
9627c478bd9Sstevel@tonic-gate 	return (0);
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate out:
9657c478bd9Sstevel@tonic-gate 	free(iprop->sc_property_name);
9667c478bd9Sstevel@tonic-gate 	internal_property_free(iprop);
9677c478bd9Sstevel@tonic-gate 	return (r);
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate /*
9717c478bd9Sstevel@tonic-gate  * Returns
9727c478bd9Sstevel@tonic-gate  *   0 - success
9737c478bd9Sstevel@tonic-gate  *   ECANCELED - pg was deleted
9747c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository disconnected
9757c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
9767c478bd9Sstevel@tonic-gate  */
9777c478bd9Sstevel@tonic-gate int
load_pg_attrs(const scf_propertygroup_t * pg,pgroup_t ** ipgp)9787c478bd9Sstevel@tonic-gate load_pg_attrs(const scf_propertygroup_t *pg, pgroup_t **ipgp)
9797c478bd9Sstevel@tonic-gate {
9807c478bd9Sstevel@tonic-gate 	pgroup_t *ipg;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	ipg = internal_pgroup_new();
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	if (scf_pg_get_flags(pg, &ipg->sc_pgroup_flags) != 0) {
9857c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
9867c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
9877c478bd9Sstevel@tonic-gate 			internal_pgroup_free(ipg);
9887c478bd9Sstevel@tonic-gate 			return (ECANCELED);
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
9917c478bd9Sstevel@tonic-gate 			internal_pgroup_free(ipg);
9927c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
9957c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
9967c478bd9Sstevel@tonic-gate 		default:
9977c478bd9Sstevel@tonic-gate 			bad_error("scf_pg_get_name", scf_error());
9987c478bd9Sstevel@tonic-gate 		}
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	if (scf_pg_get_name(pg, loadbuf, loadbuf_sz) < 0) {
10027c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
10037c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
10047c478bd9Sstevel@tonic-gate 			internal_pgroup_free(ipg);
10057c478bd9Sstevel@tonic-gate 			return (ECANCELED);
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
10087c478bd9Sstevel@tonic-gate 			internal_pgroup_free(ipg);
10097c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
10127c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
10137c478bd9Sstevel@tonic-gate 		default:
10147c478bd9Sstevel@tonic-gate 			bad_error("scf_pg_get_name", scf_error());
10157c478bd9Sstevel@tonic-gate 		}
10167c478bd9Sstevel@tonic-gate 	}
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 	ipg->sc_pgroup_name = strdup(loadbuf);
10197c478bd9Sstevel@tonic-gate 	if (ipg->sc_pgroup_name == NULL) {
10207c478bd9Sstevel@tonic-gate 		internal_pgroup_free(ipg);
10217c478bd9Sstevel@tonic-gate 		return (ENOMEM);
10227c478bd9Sstevel@tonic-gate 	}
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	if (scf_pg_get_type(pg, loadbuf, loadbuf_sz) < 0) {
10257c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
10267c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
10277c478bd9Sstevel@tonic-gate 			free((char *)ipg->sc_pgroup_name);
10287c478bd9Sstevel@tonic-gate 			internal_pgroup_free(ipg);
10297c478bd9Sstevel@tonic-gate 			return (ECANCELED);
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
10327c478bd9Sstevel@tonic-gate 			free((char *)ipg->sc_pgroup_name);
10337c478bd9Sstevel@tonic-gate 			internal_pgroup_free(ipg);
10347c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
10377c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
10387c478bd9Sstevel@tonic-gate 		default:
10397c478bd9Sstevel@tonic-gate 			bad_error("scf_pg_get_name", scf_error());
10407c478bd9Sstevel@tonic-gate 		}
10417c478bd9Sstevel@tonic-gate 	}
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	ipg->sc_pgroup_type = strdup(loadbuf);
10447c478bd9Sstevel@tonic-gate 	if (ipg->sc_pgroup_type == NULL) {
10457c478bd9Sstevel@tonic-gate 		free((char *)ipg->sc_pgroup_name);
10467c478bd9Sstevel@tonic-gate 		internal_pgroup_free(ipg);
10477c478bd9Sstevel@tonic-gate 		return (ENOMEM);
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	*ipgp = ipg;
10517c478bd9Sstevel@tonic-gate 	return (0);
10527c478bd9Sstevel@tonic-gate }
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate /*
10557c478bd9Sstevel@tonic-gate  * Load a property group into a pgroup_t.  Returns
10567c478bd9Sstevel@tonic-gate  *   0 - success
10577c478bd9Sstevel@tonic-gate  *   ECANCELED - pg was deleted
10587c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository disconnected
10597c478bd9Sstevel@tonic-gate  *   EBADF - pg is corrupt (error printed if fmri is given)
10607c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
10613eae19d9Swesolows  *   EACCES - permission denied when reading property
10627c478bd9Sstevel@tonic-gate  */
10637c478bd9Sstevel@tonic-gate int
load_pg(const scf_propertygroup_t * pg,pgroup_t ** ipgp,const char * fmri,const char * snapname)10647c478bd9Sstevel@tonic-gate load_pg(const scf_propertygroup_t *pg, pgroup_t **ipgp, const char *fmri,
10657c478bd9Sstevel@tonic-gate     const char *snapname)
10667c478bd9Sstevel@tonic-gate {
10677c478bd9Sstevel@tonic-gate 	pgroup_t *ipg;
10687c478bd9Sstevel@tonic-gate 	int r;
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 	if (scf_iter_pg_properties(load_propiter, pg) != 0) {
10717c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
10727c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
10737c478bd9Sstevel@tonic-gate 			return (ECANCELED);
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
10767c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
10797c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
10807c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_BOUND:
10817c478bd9Sstevel@tonic-gate 		default:
10827c478bd9Sstevel@tonic-gate 			bad_error("scf_iter_pg_properties", scf_error());
10837c478bd9Sstevel@tonic-gate 		}
10847c478bd9Sstevel@tonic-gate 	}
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	r = load_pg_attrs(pg, &ipg);
10877c478bd9Sstevel@tonic-gate 	switch (r) {
10887c478bd9Sstevel@tonic-gate 	case 0:
10897c478bd9Sstevel@tonic-gate 		break;
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	case ECANCELED:
10927c478bd9Sstevel@tonic-gate 	case ECONNABORTED:
10937c478bd9Sstevel@tonic-gate 	case ENOMEM:
10947c478bd9Sstevel@tonic-gate 		return (r);
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	default:
10977c478bd9Sstevel@tonic-gate 		bad_error("load_pg_attrs", r);
10987c478bd9Sstevel@tonic-gate 	}
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	for (;;) {
11017c478bd9Sstevel@tonic-gate 		property_t *iprop;
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 		r = scf_iter_next_property(load_propiter, load_prop);
11047c478bd9Sstevel@tonic-gate 		if (r == 0)
11057c478bd9Sstevel@tonic-gate 			break;
11067c478bd9Sstevel@tonic-gate 		if (r != 1) {
11077c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
11087c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
11097c478bd9Sstevel@tonic-gate 				r = ECANCELED;
11107c478bd9Sstevel@tonic-gate 				goto out;
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
11137c478bd9Sstevel@tonic-gate 				r = ECONNABORTED;
11147c478bd9Sstevel@tonic-gate 				goto out;
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
11177c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_BOUND:
11187c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
11197c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
11207c478bd9Sstevel@tonic-gate 			default:
11217c478bd9Sstevel@tonic-gate 				bad_error("scf_iter_next_property",
11227c478bd9Sstevel@tonic-gate 				    scf_error());
11237c478bd9Sstevel@tonic-gate 			}
11247c478bd9Sstevel@tonic-gate 		}
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 		r = load_property(load_prop, &iprop);
11277c478bd9Sstevel@tonic-gate 		switch (r) {
11287c478bd9Sstevel@tonic-gate 		case 0:
11297c478bd9Sstevel@tonic-gate 			break;
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 		case ECANCELED:
11327c478bd9Sstevel@tonic-gate 		case ECONNABORTED:
11337c478bd9Sstevel@tonic-gate 		case ENOMEM:
11343eae19d9Swesolows 		case EACCES:
11357c478bd9Sstevel@tonic-gate 			goto out;
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 		default:
11387c478bd9Sstevel@tonic-gate 			bad_error("load_property", r);
11397c478bd9Sstevel@tonic-gate 		}
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 		r = internal_attach_property(ipg, iprop);
11427c478bd9Sstevel@tonic-gate 		if (r != 0) {
11437c478bd9Sstevel@tonic-gate 			if (fmri != NULL) {
11447c478bd9Sstevel@tonic-gate 				if (snapname == NULL)
11457c478bd9Sstevel@tonic-gate 					warn(gettext("Property group \"%s\" of "
11467c478bd9Sstevel@tonic-gate 					    "%s has multiple definitions of "
11477c478bd9Sstevel@tonic-gate 					    "property \"%s\".\n"),
11487c478bd9Sstevel@tonic-gate 					    ipg->sc_pgroup_name, fmri,
11497c478bd9Sstevel@tonic-gate 					    iprop->sc_property_name);
11507c478bd9Sstevel@tonic-gate 				else
11517c478bd9Sstevel@tonic-gate 					warn(gettext("Property group \"%s\" of "
11527c478bd9Sstevel@tonic-gate 					    "the \"%s\" snapshot of %s has "
11537c478bd9Sstevel@tonic-gate 					    "multiple definitions of property "
11547c478bd9Sstevel@tonic-gate 					    "\"%s\".\n"),
11557c478bd9Sstevel@tonic-gate 					    ipg->sc_pgroup_name, snapname, fmri,
11567c478bd9Sstevel@tonic-gate 					    iprop->sc_property_name);
11577c478bd9Sstevel@tonic-gate 			}
11587c478bd9Sstevel@tonic-gate 			r = EBADF;
11597c478bd9Sstevel@tonic-gate 			goto out;
11607c478bd9Sstevel@tonic-gate 		}
11617c478bd9Sstevel@tonic-gate 	}
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	*ipgp = ipg;
11647c478bd9Sstevel@tonic-gate 	return (0);
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate out:
11677c478bd9Sstevel@tonic-gate 	internal_pgroup_free(ipg);
11687c478bd9Sstevel@tonic-gate 	return (r);
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate 
11711f6eb021SLiane Praza /*
11721f6eb021SLiane Praza  * Load the instance for fmri from the repository into memory.  The
11731f6eb021SLiane Praza  * property groups that define the instances pg_patterns and prop_patterns
11741f6eb021SLiane Praza  * are also loaded.
11751f6eb021SLiane Praza  *
11761f6eb021SLiane Praza  * Returns 0 on success and non-zero on failure.
11771f6eb021SLiane Praza  */
11781f6eb021SLiane Praza int
load_instance(const char * fmri,const char * name,entity_t ** inst_ptr)11791f6eb021SLiane Praza load_instance(const char *fmri, const char *name, entity_t **inst_ptr)
11801f6eb021SLiane Praza {
11811f6eb021SLiane Praza 	entity_t *e = NULL;
11821f6eb021SLiane Praza 	scf_instance_t *inst;
11831f6eb021SLiane Praza 	pgroup_t *ipg;
11841f6eb021SLiane Praza 	int rc;
11851f6eb021SLiane Praza 	char *type = NULL;
11861f6eb021SLiane Praza 	ssize_t tsize;
11871f6eb021SLiane Praza 
11881f6eb021SLiane Praza 	assert(inst_ptr != NULL);
11891f6eb021SLiane Praza 
11901f6eb021SLiane Praza 	if ((inst = scf_instance_create(g_hndl)) == NULL) {
11911f6eb021SLiane Praza 		switch (scf_error()) {
11921f6eb021SLiane Praza 		case SCF_ERROR_NO_MEMORY:
11931f6eb021SLiane Praza 		case SCF_ERROR_NO_RESOURCES:
11941f6eb021SLiane Praza 			rc = EAGAIN;
11951f6eb021SLiane Praza 			goto errout;
11961f6eb021SLiane Praza 		default:
11971f6eb021SLiane Praza 			bad_error("scf_instance_create", scf_error());
11981f6eb021SLiane Praza 		}
11991f6eb021SLiane Praza 	}
12001f6eb021SLiane Praza 	if (scf_handle_decode_fmri(g_hndl, fmri, NULL, NULL, inst, NULL, NULL,
12011f6eb021SLiane Praza 	    SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
12021f6eb021SLiane Praza 		switch (scf_error()) {
12031f6eb021SLiane Praza 		case SCF_ERROR_CONNECTION_BROKEN:
12041f6eb021SLiane Praza 			rc = ECONNABORTED;
12051f6eb021SLiane Praza 			goto errout;
12061f6eb021SLiane Praza 		case SCF_ERROR_DELETED:
12071f6eb021SLiane Praza 		case SCF_ERROR_NOT_FOUND:
12081f6eb021SLiane Praza 			rc = ENOENT;
12091f6eb021SLiane Praza 			goto errout;
1210870ad75aSSean Wilcox 		case SCF_ERROR_INVALID_ARGUMENT:
1211870ad75aSSean Wilcox 			rc = EINVAL;
1212870ad75aSSean Wilcox 			goto errout;
1213870ad75aSSean Wilcox 		case SCF_ERROR_CONSTRAINT_VIOLATED:
1214870ad75aSSean Wilcox 			rc = ENOTSUP;
1215870ad75aSSean Wilcox 			goto errout;
12161f6eb021SLiane Praza 		default:
12171f6eb021SLiane Praza 			bad_error("scf_handle_decode_fmri", scf_error());
12181f6eb021SLiane Praza 		}
12191f6eb021SLiane Praza 	}
12201f6eb021SLiane Praza 	if (scf_iter_instance_pgs_composed(load_pgiter, inst, NULL) != 0) {
12211f6eb021SLiane Praza 		switch (scf_error()) {
12221f6eb021SLiane Praza 		case SCF_ERROR_DELETED:
12231f6eb021SLiane Praza 			rc = ECANCELED;
12241f6eb021SLiane Praza 			goto errout;
12251f6eb021SLiane Praza 		case SCF_ERROR_CONNECTION_BROKEN:
12261f6eb021SLiane Praza 			rc = ECONNABORTED;
12271f6eb021SLiane Praza 			goto errout;
12281f6eb021SLiane Praza 		default:
12291f6eb021SLiane Praza 			bad_error("scf_iter_instance_pgs_composed",
12301f6eb021SLiane Praza 			    scf_error());
12311f6eb021SLiane Praza 		}
12321f6eb021SLiane Praza 	}
12331f6eb021SLiane Praza 
12341f6eb021SLiane Praza 	tsize = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH);
12351f6eb021SLiane Praza 	type = uu_zalloc(tsize);
12361f6eb021SLiane Praza 	if (type == NULL) {
12371f6eb021SLiane Praza 		rc = ENOMEM;
12381f6eb021SLiane Praza 		goto errout;
12391f6eb021SLiane Praza 	}
12401f6eb021SLiane Praza 
12411f6eb021SLiane Praza 	/*
12421f6eb021SLiane Praza 	 * Initialize our entity structure.
12431f6eb021SLiane Praza 	 */
12441f6eb021SLiane Praza 	e = internal_instance_new(name);
12451f6eb021SLiane Praza 	if (e == NULL) {
12461f6eb021SLiane Praza 		rc = ENOMEM;
12471f6eb021SLiane Praza 		goto errout;
12481f6eb021SLiane Praza 	}
12491f6eb021SLiane Praza 	e->sc_fmri = uu_strdup(fmri);
12501f6eb021SLiane Praza 	if (e->sc_fmri == NULL) {
12511f6eb021SLiane Praza 		rc = ENOMEM;
12521f6eb021SLiane Praza 		goto errout;
12531f6eb021SLiane Praza 	}
12541f6eb021SLiane Praza 
12551f6eb021SLiane Praza 	/*
12561f6eb021SLiane Praza 	 * Walk through the property group's of the instance and capture
12571f6eb021SLiane Praza 	 * the property groups that are of type
12581f6eb021SLiane Praza 	 * SCF_GROUP_TEMPLATE_PG_PATTERN and
12591f6eb021SLiane Praza 	 * SCF_GROUP_TEMPLATE_PROP_PATTERN.  In other words grab the
12601f6eb021SLiane Praza 	 * pg_pattern and prop_pattern property groups.
12611f6eb021SLiane Praza 	 */
12621f6eb021SLiane Praza 	while ((rc = scf_iter_next_pg(load_pgiter, load_pgroup)) == 1) {
12631f6eb021SLiane Praza 		if (scf_pg_get_type(load_pgroup, type, tsize) <= 0) {
12641f6eb021SLiane Praza 			switch (scf_error()) {
12651f6eb021SLiane Praza 			case SCF_ERROR_DELETED:
12661f6eb021SLiane Praza 				rc = ENOENT;
12671f6eb021SLiane Praza 				break;
12681f6eb021SLiane Praza 			case SCF_ERROR_CONNECTION_BROKEN:
12691f6eb021SLiane Praza 				rc = ECONNABORTED;
12701f6eb021SLiane Praza 				break;
12711f6eb021SLiane Praza 			default:
12721f6eb021SLiane Praza 				bad_error("scf_pg_get_type", scf_error());
12731f6eb021SLiane Praza 			}
12741f6eb021SLiane Praza 			goto errout;
12751f6eb021SLiane Praza 		}
12761f6eb021SLiane Praza 		if ((strcmp(type, SCF_GROUP_TEMPLATE_PG_PATTERN) != 0) &&
12771f6eb021SLiane Praza 		    (strcmp(type, SCF_GROUP_TEMPLATE_PROP_PATTERN) != 0)) {
12781f6eb021SLiane Praza 			continue;
12791f6eb021SLiane Praza 		}
12801f6eb021SLiane Praza 		if ((rc = load_pg(load_pgroup, &ipg, fmri, NULL)) != 0) {
12811f6eb021SLiane Praza 			switch (rc) {
12821f6eb021SLiane Praza 			case ECANCELED:
12831f6eb021SLiane Praza 			case ECONNABORTED:
12841f6eb021SLiane Praza 			case EACCES:
12851f6eb021SLiane Praza 			case ENOMEM:
12861f6eb021SLiane Praza 				break;
12871f6eb021SLiane Praza 			default:
12881f6eb021SLiane Praza 				bad_error("load_pg", rc);
12891f6eb021SLiane Praza 			}
12901f6eb021SLiane Praza 			goto errout;
12911f6eb021SLiane Praza 		}
12921f6eb021SLiane Praza 		if (internal_attach_pgroup(e, ipg) != 0) {
12931f6eb021SLiane Praza 			rc = EBADF;
12941f6eb021SLiane Praza 			goto errout;
12951f6eb021SLiane Praza 		}
12961f6eb021SLiane Praza 	}
12971f6eb021SLiane Praza 	if (rc == -1) {
12981f6eb021SLiane Praza 		/* Error in iteration. */
12991f6eb021SLiane Praza 		switch (scf_error()) {
13001f6eb021SLiane Praza 		case SCF_ERROR_CONNECTION_BROKEN:
13011f6eb021SLiane Praza 			rc = ECONNABORTED;
13021f6eb021SLiane Praza 			break;
13031f6eb021SLiane Praza 		case SCF_ERROR_DELETED:
13041f6eb021SLiane Praza 			rc = ENOENT;
13051f6eb021SLiane Praza 			break;
13061f6eb021SLiane Praza 		case SCF_ERROR_NO_RESOURCES:
13071f6eb021SLiane Praza 			rc = EAGAIN;
13081f6eb021SLiane Praza 			break;
13091f6eb021SLiane Praza 		default:
13101f6eb021SLiane Praza 			bad_error("scf_iter_next_pg", scf_error());
13111f6eb021SLiane Praza 		}
13121f6eb021SLiane Praza 		goto errout;
13131f6eb021SLiane Praza 	}
13141f6eb021SLiane Praza 
13151f6eb021SLiane Praza 	*inst_ptr = e;
13161f6eb021SLiane Praza 	scf_instance_destroy(inst);
13171f6eb021SLiane Praza 	return (0);
13181f6eb021SLiane Praza 
13191f6eb021SLiane Praza errout:
13201f6eb021SLiane Praza 	if (type != NULL)
13211f6eb021SLiane Praza 		uu_free(type);
13221f6eb021SLiane Praza 	if (inst != NULL)
13231f6eb021SLiane Praza 		scf_instance_destroy(inst);
13241f6eb021SLiane Praza 	if (e != NULL)
13251f6eb021SLiane Praza 		internal_instance_free(e);
13261f6eb021SLiane Praza 	return (rc);
13271f6eb021SLiane Praza }
13281f6eb021SLiane Praza 
13297c478bd9Sstevel@tonic-gate /*
13307c478bd9Sstevel@tonic-gate  * These functions compare internal property groups and properties (pgroup_t
13317c478bd9Sstevel@tonic-gate  * & property_t).  They return 1 if the given structures are equal and
13327c478bd9Sstevel@tonic-gate  * 0 otherwise.  Some will report the differences between the two structures.
13337c478bd9Sstevel@tonic-gate  * They are used by the import functions in svccfg_libscf.c .
13347c478bd9Sstevel@tonic-gate  */
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate int
prop_equal(property_t * p1,property_t * p2,const char * fmri,const char * pgname,int new)13377c478bd9Sstevel@tonic-gate prop_equal(property_t *p1, property_t *p2, const char *fmri, const char *pgname,
13387c478bd9Sstevel@tonic-gate     int new)
13397c478bd9Sstevel@tonic-gate {
13407c478bd9Sstevel@tonic-gate 	value_t *v1, *v2;
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	const char * const values_diff = gettext("Conflict upgrading %s "
13437c478bd9Sstevel@tonic-gate 	    "(property \"%s/%s\" has different values).\n");
13447c478bd9Sstevel@tonic-gate 	const char * const values_diff_new = gettext("Conflict upgrading %s "
13457c478bd9Sstevel@tonic-gate 	    "(new property \"%s/%s\" has different values).\n");
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 	assert((fmri == NULL) == (pgname == NULL));
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	if (fmri != NULL) {
13507c478bd9Sstevel@tonic-gate 		/*
13517c478bd9Sstevel@tonic-gate 		 * If we find any differences, we'll report conflicts.  But
13527c478bd9Sstevel@tonic-gate 		 * conflict messages won't make any sense if the names don't
13537c478bd9Sstevel@tonic-gate 		 * match.  If the caller supplied fmri, assert that the names
13547c478bd9Sstevel@tonic-gate 		 * match.
13557c478bd9Sstevel@tonic-gate 		 */
13567c478bd9Sstevel@tonic-gate 		assert(strcmp(p1->sc_property_name, p2->sc_property_name) == 0);
13577c478bd9Sstevel@tonic-gate 	} else {
13587c478bd9Sstevel@tonic-gate 		if (strcmp(p1->sc_property_name, p2->sc_property_name) != 0)
13597c478bd9Sstevel@tonic-gate 			return (0);
13607c478bd9Sstevel@tonic-gate 	}
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 	if (p1->sc_value_type != p2->sc_value_type) {
13637c478bd9Sstevel@tonic-gate 		if (fmri != NULL) {
13647c478bd9Sstevel@tonic-gate 			if (new)
13657c478bd9Sstevel@tonic-gate 				warn(gettext("Conflict upgrading %s "
13667c478bd9Sstevel@tonic-gate 				    "(new property \"%s/%s\" has different "
13677c478bd9Sstevel@tonic-gate 				    "type).\n"), fmri, pgname,
13687c478bd9Sstevel@tonic-gate 				    p1->sc_property_name);
13697c478bd9Sstevel@tonic-gate 			else
13707c478bd9Sstevel@tonic-gate 				warn(gettext("Conflict upgrading %s "
13717c478bd9Sstevel@tonic-gate 				    "(property \"%s/%s\" has different "
13727c478bd9Sstevel@tonic-gate 				    "type).\n"), fmri, pgname,
13737c478bd9Sstevel@tonic-gate 				    p1->sc_property_name);
13747c478bd9Sstevel@tonic-gate 		}
13757c478bd9Sstevel@tonic-gate 		return (0);
13767c478bd9Sstevel@tonic-gate 	}
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 	if (uu_list_numnodes(p1->sc_property_values) !=
13797c478bd9Sstevel@tonic-gate 	    uu_list_numnodes(p2->sc_property_values)) {
13807c478bd9Sstevel@tonic-gate 		if (fmri != NULL)
13817c478bd9Sstevel@tonic-gate 			warn(new ? values_diff_new : values_diff, fmri,
13827c478bd9Sstevel@tonic-gate 			    pgname, p1->sc_property_name);
13837c478bd9Sstevel@tonic-gate 		return (0);
13847c478bd9Sstevel@tonic-gate 	}
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	v1 = uu_list_first(p1->sc_property_values);
13877c478bd9Sstevel@tonic-gate 	v2 = uu_list_first(p2->sc_property_values);
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 	while (v1 != NULL) {
13907c478bd9Sstevel@tonic-gate 		assert(v2 != NULL);
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 		if (value_cmp(v1, v2, NULL) != 0) {
13937c478bd9Sstevel@tonic-gate 			if (fmri != NULL)
13947c478bd9Sstevel@tonic-gate 				warn(new ? values_diff_new : values_diff,
13957c478bd9Sstevel@tonic-gate 				    fmri, pgname, p1->sc_property_name);
13967c478bd9Sstevel@tonic-gate 			return (0);
13977c478bd9Sstevel@tonic-gate 		}
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 		v1 = uu_list_next(p1->sc_property_values, v1);
14007c478bd9Sstevel@tonic-gate 		v2 = uu_list_next(p2->sc_property_values, v2);
14017c478bd9Sstevel@tonic-gate 	}
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	return (1);
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate int
pg_attrs_equal(const pgroup_t * pg1,const pgroup_t * pg2,const char * fmri,int new)14079e9ae1fcSbustos pg_attrs_equal(const pgroup_t *pg1, const pgroup_t *pg2, const char *fmri,
14089e9ae1fcSbustos     int new)
14097c478bd9Sstevel@tonic-gate {
14107c478bd9Sstevel@tonic-gate 	if (strcmp(pg1->sc_pgroup_name, pg2->sc_pgroup_name) != 0) {
14117c478bd9Sstevel@tonic-gate 		assert(fmri == NULL);
14127c478bd9Sstevel@tonic-gate 		return (0);
14137c478bd9Sstevel@tonic-gate 	}
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate 	if (pg1->sc_pgroup_flags != pg2->sc_pgroup_flags) {
14167c478bd9Sstevel@tonic-gate 		if (fmri) {
14177c478bd9Sstevel@tonic-gate 			if (new)
14187c478bd9Sstevel@tonic-gate 				warn(gettext("Conflict upgrading %s "
14197c478bd9Sstevel@tonic-gate 				    "(new property group \"%s\" has different "
14207c478bd9Sstevel@tonic-gate 				    "flags).\n"), fmri, pg1->sc_pgroup_name);
14217c478bd9Sstevel@tonic-gate 			else
14227c478bd9Sstevel@tonic-gate 				warn(gettext("Conflict upgrading %s "
14237c478bd9Sstevel@tonic-gate 				    "(property group \"%s\" has different "
14247c478bd9Sstevel@tonic-gate 				    "flags).\n"), fmri, pg1->sc_pgroup_name);
14257c478bd9Sstevel@tonic-gate 		}
14267c478bd9Sstevel@tonic-gate 		return (0);
14277c478bd9Sstevel@tonic-gate 	}
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 	if (strcmp(pg1->sc_pgroup_type, pg2->sc_pgroup_type) != 0) {
14307c478bd9Sstevel@tonic-gate 		if (fmri) {
14317c478bd9Sstevel@tonic-gate 			if (new)
14327c478bd9Sstevel@tonic-gate 				warn(gettext("Conflict upgrading %s "
14337c478bd9Sstevel@tonic-gate 				    "(new property group \"%s\" has different "
14347c478bd9Sstevel@tonic-gate 				    "type).\n"), fmri, pg1->sc_pgroup_name);
14357c478bd9Sstevel@tonic-gate 			else
14367c478bd9Sstevel@tonic-gate 				warn(gettext("Conflict upgrading %s "
14377c478bd9Sstevel@tonic-gate 				    "(property group \"%s\" has different "
14387c478bd9Sstevel@tonic-gate 				    "type).\n"), fmri, pg1->sc_pgroup_name);
14397c478bd9Sstevel@tonic-gate 		}
14407c478bd9Sstevel@tonic-gate 		return (0);
14417c478bd9Sstevel@tonic-gate 	}
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	return (1);
14447c478bd9Sstevel@tonic-gate }
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate int
pg_equal(pgroup_t * pg1,pgroup_t * pg2)14477c478bd9Sstevel@tonic-gate pg_equal(pgroup_t *pg1, pgroup_t *pg2)
14487c478bd9Sstevel@tonic-gate {
14497c478bd9Sstevel@tonic-gate 	property_t *p1, *p2;
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	if (!pg_attrs_equal(pg1, pg2, NULL, 0))
14527c478bd9Sstevel@tonic-gate 		return (0);
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 	if (uu_list_numnodes(pg1->sc_pgroup_props) !=
14557c478bd9Sstevel@tonic-gate 	    uu_list_numnodes(pg2->sc_pgroup_props))
14567c478bd9Sstevel@tonic-gate 		return (0);
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	p1 = uu_list_first(pg1->sc_pgroup_props);
14597c478bd9Sstevel@tonic-gate 	p2 = uu_list_first(pg2->sc_pgroup_props);
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 	while (p1 != NULL) {
14627c478bd9Sstevel@tonic-gate 		assert(p2 != NULL);
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 		if (!prop_equal(p1, p2, NULL, NULL, 0))
14657c478bd9Sstevel@tonic-gate 			return (0);
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 		p1 = uu_list_next(pg1->sc_pgroup_props, p1);
14687c478bd9Sstevel@tonic-gate 		p2 = uu_list_next(pg2->sc_pgroup_props, p2);
14697c478bd9Sstevel@tonic-gate 	}
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate 	return (1);
14727c478bd9Sstevel@tonic-gate }
1473