10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55040Swesolows * Common Development and Distribution License (the "License").
65040Swesolows * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
215040Swesolows
220Sstevel@tonic-gate /*
23*12667SSean.Wilcox@Sun.COM * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <assert.h>
270Sstevel@tonic-gate #include <errno.h>
280Sstevel@tonic-gate #include <libintl.h>
290Sstevel@tonic-gate #include <libuutil.h>
300Sstevel@tonic-gate #include <stdarg.h>
310Sstevel@tonic-gate #include <stddef.h>
320Sstevel@tonic-gate #include <string.h>
337887SLiane.Praza@Sun.COM #include <unistd.h>
347887SLiane.Praza@Sun.COM #include <libscf_priv.h>
350Sstevel@tonic-gate
360Sstevel@tonic-gate #include "svccfg.h"
370Sstevel@tonic-gate
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate * Internal representation manipulation routines for svccfg(1)
400Sstevel@tonic-gate */
410Sstevel@tonic-gate
420Sstevel@tonic-gate static uu_list_pool_t *entity_pool;
430Sstevel@tonic-gate static uu_list_pool_t *pgroup_pool;
440Sstevel@tonic-gate static uu_list_pool_t *property_pool;
450Sstevel@tonic-gate static uu_list_pool_t *value_pool;
460Sstevel@tonic-gate
470Sstevel@tonic-gate /* ARGSUSED */
480Sstevel@tonic-gate static int
entity_cmp(const void * a,const void * b,void * p)490Sstevel@tonic-gate entity_cmp(const void *a, const void *b, void *p)
500Sstevel@tonic-gate {
510Sstevel@tonic-gate entity_t *A = (entity_t *)a;
520Sstevel@tonic-gate entity_t *B = (entity_t *)b;
530Sstevel@tonic-gate
540Sstevel@tonic-gate return (strcmp(A->sc_name, B->sc_name));
550Sstevel@tonic-gate }
560Sstevel@tonic-gate
570Sstevel@tonic-gate /*ARGSUSED*/
580Sstevel@tonic-gate static int
pgroup_cmp(const void * a,const void * b,void * p)590Sstevel@tonic-gate pgroup_cmp(const void *a, const void *b, void *p)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate pgroup_t *A = (pgroup_t *)a;
620Sstevel@tonic-gate pgroup_t *B = (pgroup_t *)b;
630Sstevel@tonic-gate
640Sstevel@tonic-gate return (strcmp(A->sc_pgroup_name, B->sc_pgroup_name));
650Sstevel@tonic-gate }
660Sstevel@tonic-gate
670Sstevel@tonic-gate /* ARGSUSED */
680Sstevel@tonic-gate static int
property_cmp(const void * a,const void * b,void * p)690Sstevel@tonic-gate property_cmp(const void *a, const void *b, void *p)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate property_t *A = (property_t *)a;
720Sstevel@tonic-gate property_t *B = (property_t *)b;
730Sstevel@tonic-gate
740Sstevel@tonic-gate return (strcmp(A->sc_property_name, B->sc_property_name));
750Sstevel@tonic-gate }
760Sstevel@tonic-gate
770Sstevel@tonic-gate /* ARGSUSED */
780Sstevel@tonic-gate int
value_cmp(const void * a,const void * b,void * p)790Sstevel@tonic-gate value_cmp(const void *a, const void *b, void *p)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate const value_t *A = a;
820Sstevel@tonic-gate const value_t *B = b;
830Sstevel@tonic-gate
840Sstevel@tonic-gate if (A->sc_type != B->sc_type)
850Sstevel@tonic-gate return (B->sc_type - A->sc_type);
860Sstevel@tonic-gate
870Sstevel@tonic-gate switch (A->sc_type) {
880Sstevel@tonic-gate case SCF_TYPE_BOOLEAN:
890Sstevel@tonic-gate case SCF_TYPE_COUNT:
900Sstevel@tonic-gate return (B->sc_u.sc_count - A->sc_u.sc_count);
910Sstevel@tonic-gate
920Sstevel@tonic-gate case SCF_TYPE_INTEGER:
930Sstevel@tonic-gate return (B->sc_u.sc_integer - A->sc_u.sc_integer);
940Sstevel@tonic-gate
950Sstevel@tonic-gate default:
960Sstevel@tonic-gate return (strcmp(A->sc_u.sc_string, B->sc_u.sc_string));
970Sstevel@tonic-gate }
980Sstevel@tonic-gate }
990Sstevel@tonic-gate
1000Sstevel@tonic-gate void
internal_init()1010Sstevel@tonic-gate internal_init()
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate if ((entity_pool = uu_list_pool_create("entities", sizeof (entity_t),
1040Sstevel@tonic-gate offsetof(entity_t, sc_node), entity_cmp, 0)) == NULL)
1050Sstevel@tonic-gate uu_die(gettext("entity list pool creation failed: %s\n"),
1060Sstevel@tonic-gate uu_strerror(uu_error()));
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate if ((pgroup_pool = uu_list_pool_create("property_groups",
1090Sstevel@tonic-gate sizeof (pgroup_t), offsetof(pgroup_t, sc_node), pgroup_cmp, 0)) ==
1100Sstevel@tonic-gate NULL)
1110Sstevel@tonic-gate uu_die(
1120Sstevel@tonic-gate gettext("property group list pool creation failed: %s\n"),
1130Sstevel@tonic-gate uu_strerror(uu_error()));
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate if ((property_pool = uu_list_pool_create("properties",
1160Sstevel@tonic-gate sizeof (property_t), offsetof(property_t, sc_node), property_cmp,
1170Sstevel@tonic-gate 0)) == NULL)
1180Sstevel@tonic-gate uu_die(gettext("property list pool creation failed: %s\n"),
1190Sstevel@tonic-gate uu_strerror(uu_error()));
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate if ((value_pool = uu_list_pool_create("property_values",
1220Sstevel@tonic-gate sizeof (value_t), offsetof(value_t, sc_node), value_cmp, 0)) ==
1230Sstevel@tonic-gate NULL)
1240Sstevel@tonic-gate uu_die(
1250Sstevel@tonic-gate gettext("property value list pool creation failed: %s\n"),
1260Sstevel@tonic-gate uu_strerror(uu_error()));
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate /*ARGSUSED*/
1300Sstevel@tonic-gate static int
internal_value_dump(void * v,void * pvt)1310Sstevel@tonic-gate internal_value_dump(void *v, void *pvt)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate value_t *val = v;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate switch (val->sc_type) {
1360Sstevel@tonic-gate case SCF_TYPE_BOOLEAN:
1370Sstevel@tonic-gate (void) printf(" value = %s\n",
1380Sstevel@tonic-gate val->sc_u.sc_count ? "true" : "false");
1390Sstevel@tonic-gate break;
1400Sstevel@tonic-gate case SCF_TYPE_COUNT:
1410Sstevel@tonic-gate (void) printf(" value = %llu\n", val->sc_u.sc_count);
1420Sstevel@tonic-gate break;
1430Sstevel@tonic-gate case SCF_TYPE_INTEGER:
1440Sstevel@tonic-gate (void) printf(" value = %lld\n", val->sc_u.sc_integer);
1450Sstevel@tonic-gate break;
1460Sstevel@tonic-gate case SCF_TYPE_ASTRING:
1470Sstevel@tonic-gate case SCF_TYPE_FMRI:
1480Sstevel@tonic-gate case SCF_TYPE_HOST:
1490Sstevel@tonic-gate case SCF_TYPE_HOSTNAME:
1500Sstevel@tonic-gate case SCF_TYPE_NET_ADDR_V4:
1510Sstevel@tonic-gate case SCF_TYPE_NET_ADDR_V6:
1520Sstevel@tonic-gate case SCF_TYPE_OPAQUE:
1530Sstevel@tonic-gate case SCF_TYPE_TIME:
1540Sstevel@tonic-gate case SCF_TYPE_URI:
1550Sstevel@tonic-gate case SCF_TYPE_USTRING:
1560Sstevel@tonic-gate (void) printf(" value = %s\n",
1570Sstevel@tonic-gate val->sc_u.sc_string ? val->sc_u.sc_string : "(nil)");
1580Sstevel@tonic-gate break;
1590Sstevel@tonic-gate default:
1600Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), val->sc_type);
1610Sstevel@tonic-gate break;
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate return (UU_WALK_NEXT);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate /*ARGSUSED*/
1680Sstevel@tonic-gate static int
internal_property_dump(void * v,void * pvt)1690Sstevel@tonic-gate internal_property_dump(void *v, void *pvt)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate property_t *p = v;
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate (void) printf("property\n name = %s\n", p->sc_property_name);
1740Sstevel@tonic-gate (void) printf(" type = %d\n", p->sc_value_type);
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate (void) uu_list_walk(p->sc_property_values, internal_value_dump,
1770Sstevel@tonic-gate NULL, UU_DEFAULT);
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate return (UU_WALK_NEXT);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /*ARGSUSED*/
1830Sstevel@tonic-gate static int
internal_pgroup_dump(void * v,void * pvt)1840Sstevel@tonic-gate internal_pgroup_dump(void *v, void *pvt)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate pgroup_t *pg = v;
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate (void) printf("pgroup name = %s\n", pg->sc_pgroup_name);
1890Sstevel@tonic-gate (void) printf(" type = %s\n", pg->sc_pgroup_type);
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate (void) uu_list_walk(pg->sc_pgroup_props, internal_property_dump,
1920Sstevel@tonic-gate NULL, UU_DEFAULT);
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate return (UU_WALK_NEXT);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /*ARGSUSED*/
1980Sstevel@tonic-gate static int
internal_instance_dump(void * v,void * pvt)1990Sstevel@tonic-gate internal_instance_dump(void *v, void *pvt)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate entity_t *i = v;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate (void) printf("instance name = %s\n", i->sc_name);
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate (void) uu_list_walk(i->sc_pgroups, internal_pgroup_dump, NULL,
2060Sstevel@tonic-gate UU_DEFAULT);
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate return (UU_WALK_NEXT);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate /*ARGSUSED*/
2120Sstevel@tonic-gate static int
internal_service_dump(void * v,void * pvt)2130Sstevel@tonic-gate internal_service_dump(void *v, void *pvt)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate entity_t *s = v;
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate (void) printf("service name = %s\n", s->sc_name);
2180Sstevel@tonic-gate (void) printf(" type = %x\n", s->sc_u.sc_service.sc_service_type);
2190Sstevel@tonic-gate (void) printf(" version = %u\n", s->sc_u.sc_service.sc_service_version);
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate (void) uu_list_walk(s->sc_pgroups, internal_pgroup_dump, NULL,
2220Sstevel@tonic-gate UU_DEFAULT);
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate (void) uu_list_walk(s->sc_u.sc_service.sc_service_instances,
2250Sstevel@tonic-gate internal_instance_dump, NULL, UU_DEFAULT);
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate return (UU_WALK_NEXT);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate void
internal_dump(bundle_t * b)2310Sstevel@tonic-gate internal_dump(bundle_t *b)
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate (void) printf("bundle name = %s\n", b->sc_bundle_name);
2340Sstevel@tonic-gate (void) printf(" type = %x\n", b->sc_bundle_type);
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate (void) uu_list_walk(b->sc_bundle_services, internal_service_dump,
2370Sstevel@tonic-gate NULL, UU_DEFAULT);
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate bundle_t *
internal_bundle_new()2410Sstevel@tonic-gate internal_bundle_new()
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate bundle_t *b;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate if ((b = uu_zalloc(sizeof (bundle_t))) == NULL)
2460Sstevel@tonic-gate uu_die(gettext("couldn't allocate memory"));
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate b->sc_bundle_type = SVCCFG_UNKNOWN_BUNDLE;
2490Sstevel@tonic-gate b->sc_bundle_services = uu_list_create(entity_pool, b, 0);
2507887SLiane.Praza@Sun.COM if (b->sc_bundle_services == NULL) {
2517887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for bundle services. "
2527887SLiane.Praza@Sun.COM "%s\n"), uu_strerror(uu_error()));
2537887SLiane.Praza@Sun.COM }
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate return (b);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate void
internal_bundle_free(bundle_t * b)2590Sstevel@tonic-gate internal_bundle_free(bundle_t *b)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate void *cookie = NULL;
2620Sstevel@tonic-gate entity_t *service;
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate while ((service = uu_list_teardown(b->sc_bundle_services, &cookie)) !=
2650Sstevel@tonic-gate NULL)
2660Sstevel@tonic-gate internal_service_free(service);
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate free(b);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate entity_t *
internal_entity_new(entity_type_t entity)2727887SLiane.Praza@Sun.COM internal_entity_new(entity_type_t entity)
2737887SLiane.Praza@Sun.COM {
2747887SLiane.Praza@Sun.COM entity_t *e;
2757887SLiane.Praza@Sun.COM
2767887SLiane.Praza@Sun.COM if ((e = uu_zalloc(sizeof (entity_t))) == NULL)
2777887SLiane.Praza@Sun.COM uu_die(gettext("couldn't allocate memory"));
2787887SLiane.Praza@Sun.COM
2797887SLiane.Praza@Sun.COM uu_list_node_init(e, &e->sc_node, entity_pool);
2807887SLiane.Praza@Sun.COM
2817887SLiane.Praza@Sun.COM e->sc_etype = entity;
2827887SLiane.Praza@Sun.COM e->sc_pgroups = uu_list_create(pgroup_pool, e, 0);
283*12667SSean.Wilcox@Sun.COM e->sc_op = SVCCFG_OP_NONE;
2847887SLiane.Praza@Sun.COM if (e->sc_pgroups == NULL) {
2857887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for entity property "
2867887SLiane.Praza@Sun.COM "groups. %s\n"), uu_strerror(uu_error()));
2877887SLiane.Praza@Sun.COM }
2887887SLiane.Praza@Sun.COM
2897887SLiane.Praza@Sun.COM return (e);
2907887SLiane.Praza@Sun.COM }
2917887SLiane.Praza@Sun.COM
2927887SLiane.Praza@Sun.COM entity_t *
internal_service_new(const char * name)2930Sstevel@tonic-gate internal_service_new(const char *name)
2940Sstevel@tonic-gate {
2950Sstevel@tonic-gate entity_t *s;
2960Sstevel@tonic-gate
2977887SLiane.Praza@Sun.COM s = internal_entity_new(SVCCFG_SERVICE_OBJECT);
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate s->sc_name = name;
3000Sstevel@tonic-gate s->sc_fmri = uu_msprintf("svc:/%s", name);
3010Sstevel@tonic-gate if (s->sc_fmri == NULL)
3020Sstevel@tonic-gate uu_die(gettext("couldn't allocate memory"));
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate s->sc_dependents = uu_list_create(pgroup_pool, s, 0);
3057887SLiane.Praza@Sun.COM if (s->sc_dependents == NULL) {
3067887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for service dependents. "
3077887SLiane.Praza@Sun.COM "%s\n"), uu_strerror(uu_error()));
3087887SLiane.Praza@Sun.COM }
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate s->sc_u.sc_service.sc_service_type = SVCCFG_UNKNOWN_SERVICE;
3110Sstevel@tonic-gate s->sc_u.sc_service.sc_service_instances = uu_list_create(entity_pool, s,
3120Sstevel@tonic-gate 0);
3137887SLiane.Praza@Sun.COM if (s->sc_u.sc_service.sc_service_instances == NULL) {
3147887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for service instances. "
3157887SLiane.Praza@Sun.COM "%s\n"), uu_strerror(uu_error()));
3167887SLiane.Praza@Sun.COM }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate return (s);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate void
internal_service_free(entity_t * s)3220Sstevel@tonic-gate internal_service_free(entity_t *s)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate entity_t *inst;
3250Sstevel@tonic-gate pgroup_t *pg;
3260Sstevel@tonic-gate void *cookie;
3270Sstevel@tonic-gate
3287887SLiane.Praza@Sun.COM if (s->sc_u.sc_service.sc_restarter != NULL)
3297887SLiane.Praza@Sun.COM internal_instance_free(s->sc_u.sc_service.sc_restarter);
3307887SLiane.Praza@Sun.COM if (s->sc_u.sc_service.sc_global != NULL)
3317887SLiane.Praza@Sun.COM internal_instance_free(s->sc_u.sc_service.sc_global);
3327887SLiane.Praza@Sun.COM
3330Sstevel@tonic-gate cookie = NULL;
3340Sstevel@tonic-gate while ((pg = uu_list_teardown(s->sc_pgroups, &cookie)) != NULL)
3350Sstevel@tonic-gate internal_pgroup_free(pg);
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate cookie = NULL;
3380Sstevel@tonic-gate while ((pg = uu_list_teardown(s->sc_dependents, &cookie)) != NULL)
3390Sstevel@tonic-gate internal_pgroup_free(pg);
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate cookie = NULL;
3420Sstevel@tonic-gate while ((inst = uu_list_teardown(s->sc_u.sc_service.sc_service_instances,
3430Sstevel@tonic-gate &cookie)) != NULL)
3440Sstevel@tonic-gate internal_instance_free(inst);
3457887SLiane.Praza@Sun.COM uu_free((void *)s->sc_fmri);
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate free(s);
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate entity_t *
internal_instance_new(const char * name)3510Sstevel@tonic-gate internal_instance_new(const char *name)
3520Sstevel@tonic-gate {
3530Sstevel@tonic-gate entity_t *i;
3540Sstevel@tonic-gate
3557887SLiane.Praza@Sun.COM i = internal_entity_new(SVCCFG_INSTANCE_OBJECT);
3560Sstevel@tonic-gate i->sc_name = name;
3570Sstevel@tonic-gate /* Can't set i->sc_fmri until we're attached to a service. */
3580Sstevel@tonic-gate i->sc_dependents = uu_list_create(pgroup_pool, i, 0);
3597887SLiane.Praza@Sun.COM if (i->sc_dependents == NULL) {
3607887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for instance "
3617887SLiane.Praza@Sun.COM "dependents. %s\n"), uu_strerror(uu_error()));
3627887SLiane.Praza@Sun.COM }
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate return (i);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate void
internal_instance_free(entity_t * i)3680Sstevel@tonic-gate internal_instance_free(entity_t *i)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate pgroup_t *pg;
3710Sstevel@tonic-gate void *cookie = NULL;
3727887SLiane.Praza@Sun.COM entity_t *rs;
3730Sstevel@tonic-gate
3747887SLiane.Praza@Sun.COM rs = i->sc_u.sc_instance.sc_instance_restarter;
3757887SLiane.Praza@Sun.COM if (rs != NULL)
3767887SLiane.Praza@Sun.COM internal_instance_free(rs);
3770Sstevel@tonic-gate while ((pg = uu_list_teardown(i->sc_pgroups, &cookie)) != NULL)
3780Sstevel@tonic-gate internal_pgroup_free(pg);
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate cookie = NULL;
3810Sstevel@tonic-gate while ((pg = uu_list_teardown(i->sc_dependents, &cookie)) != NULL)
3820Sstevel@tonic-gate internal_pgroup_free(pg);
3837887SLiane.Praza@Sun.COM uu_free((void *)i->sc_fmri);
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate free(i);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate pgroup_t *
internal_pgroup_new()3890Sstevel@tonic-gate internal_pgroup_new()
3900Sstevel@tonic-gate {
3910Sstevel@tonic-gate pgroup_t *p;
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate if ((p = uu_zalloc(sizeof (pgroup_t))) == NULL)
3940Sstevel@tonic-gate uu_die(gettext("couldn't allocate memory"));
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate uu_list_node_init(p, &p->sc_node, pgroup_pool);
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate p->sc_pgroup_props = uu_list_create(property_pool, p, UU_LIST_SORTED);
3997887SLiane.Praza@Sun.COM if (p->sc_pgroup_props == NULL) {
4007887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for properties. %s\n"),
4017887SLiane.Praza@Sun.COM uu_strerror(uu_error()));
4027887SLiane.Praza@Sun.COM }
4030Sstevel@tonic-gate p->sc_pgroup_name = "<unset>";
4040Sstevel@tonic-gate p->sc_pgroup_type = "<unset>";
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate return (p);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate void
internal_pgroup_free(pgroup_t * pg)4100Sstevel@tonic-gate internal_pgroup_free(pgroup_t *pg)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate property_t *prop;
4130Sstevel@tonic-gate void *cookie = NULL;
4140Sstevel@tonic-gate
4157887SLiane.Praza@Sun.COM /*
4167887SLiane.Praza@Sun.COM * Templates validation code should clean up this reference when
4177887SLiane.Praza@Sun.COM * the validation is finished.
4187887SLiane.Praza@Sun.COM */
4197887SLiane.Praza@Sun.COM assert(pg->sc_pgroup_composed == NULL);
4207887SLiane.Praza@Sun.COM
4210Sstevel@tonic-gate while ((prop = uu_list_teardown(pg->sc_pgroup_props, &cookie)) != NULL)
4220Sstevel@tonic-gate internal_property_free(prop);
4230Sstevel@tonic-gate
424306Sbustos uu_free(pg);
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate static pgroup_t *
find_pgroup(uu_list_t * list,const char * name,const char * type)4280Sstevel@tonic-gate find_pgroup(uu_list_t *list, const char *name, const char *type)
4290Sstevel@tonic-gate {
4300Sstevel@tonic-gate pgroup_t *pg;
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate for (pg = uu_list_first(list);
4330Sstevel@tonic-gate pg != NULL;
4340Sstevel@tonic-gate pg = uu_list_next(list, pg)) {
4350Sstevel@tonic-gate if (strcmp(pg->sc_pgroup_name, name) != 0)
4360Sstevel@tonic-gate continue;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate if (type == NULL)
4390Sstevel@tonic-gate return (pg);
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate if (strcmp(pg->sc_pgroup_type, type) == 0)
4420Sstevel@tonic-gate return (pg);
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate return (NULL);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate pgroup_t *
internal_dependent_find(entity_t * e,const char * name)4490Sstevel@tonic-gate internal_dependent_find(entity_t *e, const char *name)
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate return (find_pgroup(e->sc_dependents, name, NULL));
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate pgroup_t *
internal_pgroup_find(entity_t * e,const char * name,const char * type)4550Sstevel@tonic-gate internal_pgroup_find(entity_t *e, const char *name, const char *type)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate return (find_pgroup(e->sc_pgroups, name, type));
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate
4607887SLiane.Praza@Sun.COM static pgroup_t *
internal_pgroup_create_common(entity_t * e,const char * name,const char * type,boolean_t unique)4617887SLiane.Praza@Sun.COM internal_pgroup_create_common(entity_t *e, const char *name, const char *type,
4627887SLiane.Praza@Sun.COM boolean_t unique)
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate pgroup_t *pg;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate pg = internal_pgroup_find(e, name, type);
4677887SLiane.Praza@Sun.COM if (pg != NULL) {
4687887SLiane.Praza@Sun.COM if (unique == B_TRUE) {
4697887SLiane.Praza@Sun.COM return (NULL);
4707887SLiane.Praza@Sun.COM } else {
4717887SLiane.Praza@Sun.COM return (pg);
4727887SLiane.Praza@Sun.COM }
4737887SLiane.Praza@Sun.COM }
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate pg = internal_pgroup_new();
4760Sstevel@tonic-gate (void) internal_attach_pgroup(e, pg);
4770Sstevel@tonic-gate pg->sc_pgroup_name = strdup(name);
4780Sstevel@tonic-gate pg->sc_pgroup_flags = 0;
479*12667SSean.Wilcox@Sun.COM if (type != NULL) {
480*12667SSean.Wilcox@Sun.COM pg->sc_pgroup_type = strdup(type);
481*12667SSean.Wilcox@Sun.COM } else {
482*12667SSean.Wilcox@Sun.COM est->sc_miss_type = B_TRUE;
483*12667SSean.Wilcox@Sun.COM pg->sc_pgroup_type = NULL;
484*12667SSean.Wilcox@Sun.COM }
4850Sstevel@tonic-gate
486*12667SSean.Wilcox@Sun.COM if (pg->sc_pgroup_name == NULL ||
487*12667SSean.Wilcox@Sun.COM (e->sc_op != SVCCFG_OP_APPLY && pg->sc_pgroup_type == NULL))
4880Sstevel@tonic-gate uu_die(gettext("Could not duplicate string"));
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate return (pg);
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate
4937887SLiane.Praza@Sun.COM pgroup_t *
internal_pgroup_find_or_create(entity_t * e,const char * name,const char * type)4947887SLiane.Praza@Sun.COM internal_pgroup_find_or_create(entity_t *e, const char *name, const char *type)
4957887SLiane.Praza@Sun.COM {
4967887SLiane.Praza@Sun.COM return (internal_pgroup_create_common(e, name, type, B_FALSE));
4977887SLiane.Praza@Sun.COM }
4987887SLiane.Praza@Sun.COM
4997887SLiane.Praza@Sun.COM pgroup_t *
internal_pgroup_create_strict(entity_t * e,const char * name,const char * type)5007887SLiane.Praza@Sun.COM internal_pgroup_create_strict(entity_t *e, const char *name, const char *type)
5017887SLiane.Praza@Sun.COM {
5027887SLiane.Praza@Sun.COM return (internal_pgroup_create_common(e, name, type, B_TRUE));
5037887SLiane.Praza@Sun.COM }
5047887SLiane.Praza@Sun.COM
5050Sstevel@tonic-gate property_t *
internal_property_new()5060Sstevel@tonic-gate internal_property_new()
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate property_t *p;
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate if ((p = uu_zalloc(sizeof (property_t))) == NULL)
5110Sstevel@tonic-gate uu_die(gettext("couldn't allocate memory"));
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate uu_list_node_init(p, &p->sc_node, property_pool);
5140Sstevel@tonic-gate
5157128Samaguire p->sc_property_values = uu_list_create(value_pool, p, 0);
5167887SLiane.Praza@Sun.COM if (p->sc_property_values == NULL) {
5177887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create list for property values. "
5187887SLiane.Praza@Sun.COM "%s\n"), uu_strerror(uu_error()));
5197887SLiane.Praza@Sun.COM }
5200Sstevel@tonic-gate p->sc_property_name = "<unset>";
5210Sstevel@tonic-gate
5227887SLiane.Praza@Sun.COM tmpl_property_init(p);
5237887SLiane.Praza@Sun.COM
5240Sstevel@tonic-gate return (p);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate void
internal_property_free(property_t * p)5280Sstevel@tonic-gate internal_property_free(property_t *p)
5290Sstevel@tonic-gate {
5300Sstevel@tonic-gate value_t *val;
5310Sstevel@tonic-gate void *cookie = NULL;
5320Sstevel@tonic-gate
5337887SLiane.Praza@Sun.COM tmpl_property_fini(p);
5347887SLiane.Praza@Sun.COM
5350Sstevel@tonic-gate while ((val = uu_list_teardown(p->sc_property_values, &cookie)) !=
5360Sstevel@tonic-gate NULL) {
5370Sstevel@tonic-gate if (val->sc_free != NULL)
5380Sstevel@tonic-gate val->sc_free(val);
5390Sstevel@tonic-gate free(val);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate free(p);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate property_t *
internal_property_find(pgroup_t * pg,const char * name)5460Sstevel@tonic-gate internal_property_find(pgroup_t *pg, const char *name)
5470Sstevel@tonic-gate {
5480Sstevel@tonic-gate property_t *p;
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate for (p = uu_list_first(pg->sc_pgroup_props);
5510Sstevel@tonic-gate p != NULL;
5520Sstevel@tonic-gate p = uu_list_next(pg->sc_pgroup_props, p))
5530Sstevel@tonic-gate if (strcmp(p->sc_property_name, name) == 0)
5540Sstevel@tonic-gate return (p);
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate return (NULL);
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate value_t *
internal_value_new()5600Sstevel@tonic-gate internal_value_new()
5610Sstevel@tonic-gate {
5620Sstevel@tonic-gate value_t *v;
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate if ((v = uu_zalloc(sizeof (value_t))) == NULL)
5650Sstevel@tonic-gate uu_die(gettext("couldn't allocate memory"));
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate uu_list_node_init(v, &v->sc_node, value_pool);
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate return (v);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate static void
internal_value_free_str(value_t * v)5730Sstevel@tonic-gate internal_value_free_str(value_t *v)
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate free(v->sc_u.sc_string);
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate property_t *
internal_property_create(const char * name,scf_type_t vtype,uint_t nvals,...)5790Sstevel@tonic-gate internal_property_create(const char *name, scf_type_t vtype, uint_t nvals, ...)
5800Sstevel@tonic-gate {
5810Sstevel@tonic-gate va_list args;
5820Sstevel@tonic-gate property_t *p;
5830Sstevel@tonic-gate value_t *v;
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate p = internal_property_new();
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate p->sc_property_name = (char *)name;
5880Sstevel@tonic-gate p->sc_value_type = vtype;
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate va_start(args, nvals);
5910Sstevel@tonic-gate for (; nvals > 0; nvals--) {
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate v = internal_value_new();
5940Sstevel@tonic-gate v->sc_type = vtype;
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate switch (vtype) {
5970Sstevel@tonic-gate case SCF_TYPE_BOOLEAN:
5980Sstevel@tonic-gate case SCF_TYPE_COUNT:
5990Sstevel@tonic-gate v->sc_u.sc_count = va_arg(args, uint64_t);
6000Sstevel@tonic-gate break;
6010Sstevel@tonic-gate case SCF_TYPE_INTEGER:
6020Sstevel@tonic-gate v->sc_u.sc_integer = va_arg(args, int64_t);
6030Sstevel@tonic-gate break;
6040Sstevel@tonic-gate case SCF_TYPE_ASTRING:
6050Sstevel@tonic-gate case SCF_TYPE_FMRI:
6060Sstevel@tonic-gate case SCF_TYPE_HOST:
6070Sstevel@tonic-gate case SCF_TYPE_HOSTNAME:
6080Sstevel@tonic-gate case SCF_TYPE_NET_ADDR_V4:
6090Sstevel@tonic-gate case SCF_TYPE_NET_ADDR_V6:
6100Sstevel@tonic-gate case SCF_TYPE_OPAQUE:
6110Sstevel@tonic-gate case SCF_TYPE_TIME:
6120Sstevel@tonic-gate case SCF_TYPE_URI:
6130Sstevel@tonic-gate case SCF_TYPE_USTRING:
6140Sstevel@tonic-gate v->sc_u.sc_string = (char *)va_arg(args, uchar_t *);
6150Sstevel@tonic-gate break;
6160Sstevel@tonic-gate default:
6170Sstevel@tonic-gate va_end(args);
6180Sstevel@tonic-gate uu_die(gettext("unknown property type (%d)\n"), vtype);
6190Sstevel@tonic-gate break;
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate internal_attach_value(p, v);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate va_end(args);
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate return (p);
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate /*
6300Sstevel@tonic-gate * Some of these attach functions use uu_list_append() to maintain the
6310Sstevel@tonic-gate * same order across import/export, whereas others are always sorted
6320Sstevel@tonic-gate * anyway, or the order is irrelevant.
6330Sstevel@tonic-gate */
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate int
internal_attach_service(bundle_t * bndl,entity_t * svc)6360Sstevel@tonic-gate internal_attach_service(bundle_t *bndl, entity_t *svc)
6370Sstevel@tonic-gate {
6380Sstevel@tonic-gate if (uu_list_find(bndl->sc_bundle_services, svc, NULL, NULL) != NULL) {
6390Sstevel@tonic-gate semerr(gettext("Multiple definitions for service %s in "
6400Sstevel@tonic-gate "bundle %s.\n"), svc->sc_name, bndl->sc_bundle_name);
6410Sstevel@tonic-gate return (-1);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate (void) uu_list_append(bndl->sc_bundle_services, svc);
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate return (0);
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate int
internal_attach_entity(entity_t * svc,entity_t * ent)6500Sstevel@tonic-gate internal_attach_entity(entity_t *svc, entity_t *ent)
6510Sstevel@tonic-gate {
6520Sstevel@tonic-gate if (svc->sc_etype != SVCCFG_SERVICE_OBJECT)
6530Sstevel@tonic-gate uu_die(gettext("bad entity attach: %s is not a service\n"),
6540Sstevel@tonic-gate svc->sc_name);
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate if (uu_list_find(svc->sc_u.sc_service.sc_service_instances, ent, NULL,
6570Sstevel@tonic-gate NULL) != NULL) {
6580Sstevel@tonic-gate semerr(gettext("Multiple definitions of entity %s in service "
6590Sstevel@tonic-gate "%s.\n"), ent->sc_name, svc->sc_name);
6600Sstevel@tonic-gate return (-1);
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate (void) uu_list_prepend(svc->sc_u.sc_service.sc_service_instances, ent);
6640Sstevel@tonic-gate ent->sc_parent = svc;
665*12667SSean.Wilcox@Sun.COM ent->sc_op = svc->sc_op;
6660Sstevel@tonic-gate ent->sc_fmri = uu_msprintf("%s:%s", svc->sc_fmri, ent->sc_name);
6670Sstevel@tonic-gate if (ent->sc_fmri == NULL)
6680Sstevel@tonic-gate uu_die(gettext("couldn't allocate memory"));
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate return (0);
6710Sstevel@tonic-gate }
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate int
internal_attach_pgroup(entity_t * ent,pgroup_t * pgrp)6740Sstevel@tonic-gate internal_attach_pgroup(entity_t *ent, pgroup_t *pgrp)
6750Sstevel@tonic-gate {
6760Sstevel@tonic-gate if (uu_list_find(ent->sc_pgroups, pgrp, NULL, NULL) != NULL) {
6770Sstevel@tonic-gate semerr(gettext("Multiple definitions of property group %s in "
6780Sstevel@tonic-gate "entity %s.\n"), pgrp->sc_pgroup_name, ent->sc_name);
6790Sstevel@tonic-gate return (-1);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate (void) uu_list_append(ent->sc_pgroups, pgrp);
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate pgrp->sc_parent = ent;
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate return (0);
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate
6897887SLiane.Praza@Sun.COM void
internal_detach_pgroup(entity_t * ent,pgroup_t * pgrp)6907887SLiane.Praza@Sun.COM internal_detach_pgroup(entity_t *ent, pgroup_t *pgrp)
6917887SLiane.Praza@Sun.COM {
6927887SLiane.Praza@Sun.COM uu_list_remove(ent->sc_pgroups, pgrp);
6937887SLiane.Praza@Sun.COM }
6947887SLiane.Praza@Sun.COM
6950Sstevel@tonic-gate int
internal_attach_dependent(entity_t * ent,pgroup_t * pg)6960Sstevel@tonic-gate internal_attach_dependent(entity_t *ent, pgroup_t *pg)
6970Sstevel@tonic-gate {
6980Sstevel@tonic-gate if (uu_list_find(ent->sc_dependents, pg, NULL, NULL) != NULL) {
6990Sstevel@tonic-gate semerr(gettext("Multiple definitions of dependent %s in "
7000Sstevel@tonic-gate "entity %s.\n"), pg->sc_pgroup_name, ent->sc_name);
7010Sstevel@tonic-gate return (-1);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate (void) uu_list_append(ent->sc_dependents, pg);
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate pg->sc_parent = ent;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate return (0);
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate /*
7120Sstevel@tonic-gate * Returns
7130Sstevel@tonic-gate * 0 - success
7140Sstevel@tonic-gate * -1 - prop already exists in pgrp
7150Sstevel@tonic-gate */
7160Sstevel@tonic-gate int
internal_attach_property(pgroup_t * pgrp,property_t * prop)7170Sstevel@tonic-gate internal_attach_property(pgroup_t *pgrp, property_t *prop)
7180Sstevel@tonic-gate {
7190Sstevel@tonic-gate uu_list_index_t idx;
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate if (uu_list_find(pgrp->sc_pgroup_props, prop, NULL, &idx) != NULL) {
7220Sstevel@tonic-gate semerr(gettext("Multiple definitions for property %s in "
7230Sstevel@tonic-gate "property group %s.\n"), prop->sc_property_name,
7240Sstevel@tonic-gate pgrp->sc_pgroup_name);
7250Sstevel@tonic-gate return (-1);
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate uu_list_insert(pgrp->sc_pgroup_props, prop, idx);
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate return (0);
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate void
internal_detach_property(pgroup_t * pgrp,property_t * prop)7347887SLiane.Praza@Sun.COM internal_detach_property(pgroup_t *pgrp, property_t *prop)
7357887SLiane.Praza@Sun.COM {
7367887SLiane.Praza@Sun.COM uu_list_remove(pgrp->sc_pgroup_props, prop);
7377887SLiane.Praza@Sun.COM }
7387887SLiane.Praza@Sun.COM
7397887SLiane.Praza@Sun.COM void
internal_attach_value(property_t * prop,value_t * val)7400Sstevel@tonic-gate internal_attach_value(property_t *prop, value_t *val)
7410Sstevel@tonic-gate {
7427128Samaguire (void) uu_list_append(prop->sc_property_values, val);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate /*
7460Sstevel@tonic-gate * These functions create an internal representation of a property group
7470Sstevel@tonic-gate * (pgroup_t) from the repository (scf_propertygroup_t). They are used by the
7480Sstevel@tonic-gate * import functions in svccfg_libscf.c .
7490Sstevel@tonic-gate *
7500Sstevel@tonic-gate * load_init() must be called first to initialize these globals, and
7510Sstevel@tonic-gate * load_fini() should be called afterwards to destroy them.
7520Sstevel@tonic-gate */
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate static char *loadbuf = NULL;
7550Sstevel@tonic-gate static size_t loadbuf_sz;
7567887SLiane.Praza@Sun.COM static scf_propertygroup_t *load_pgroup = NULL;
7570Sstevel@tonic-gate static scf_property_t *load_prop = NULL;
7580Sstevel@tonic-gate static scf_value_t *load_val = NULL;
7590Sstevel@tonic-gate static scf_iter_t *load_propiter = NULL, *load_valiter = NULL;
7607887SLiane.Praza@Sun.COM static scf_iter_t *load_pgiter = NULL;
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /*
7630Sstevel@tonic-gate * Initialize the global state for the load_*() routines.
7640Sstevel@tonic-gate * Returns
7650Sstevel@tonic-gate * 0 - success
7660Sstevel@tonic-gate * ENOMEM - out of memory
7670Sstevel@tonic-gate */
7680Sstevel@tonic-gate int
load_init(void)7690Sstevel@tonic-gate load_init(void)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate loadbuf_sz = ((max_scf_value_len > max_scf_pg_type_len) ?
7720Sstevel@tonic-gate max_scf_value_len : max_scf_pg_type_len) + 1;
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate loadbuf = malloc(loadbuf_sz);
7750Sstevel@tonic-gate if (loadbuf == NULL)
7760Sstevel@tonic-gate return (ENOMEM);
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate if ((load_prop = scf_property_create(g_hndl)) == NULL ||
7790Sstevel@tonic-gate (load_val = scf_value_create(g_hndl)) == NULL ||
7807887SLiane.Praza@Sun.COM (load_pgroup = scf_pg_create(g_hndl)) == NULL ||
7817887SLiane.Praza@Sun.COM (load_pgiter = scf_iter_create(g_hndl)) == NULL ||
7820Sstevel@tonic-gate (load_propiter = scf_iter_create(g_hndl)) == NULL ||
7830Sstevel@tonic-gate (load_valiter = scf_iter_create(g_hndl)) == NULL) {
7840Sstevel@tonic-gate load_fini();
7850Sstevel@tonic-gate return (ENOMEM);
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate return (0);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate void
load_fini(void)7920Sstevel@tonic-gate load_fini(void)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate scf_iter_destroy(load_propiter);
7950Sstevel@tonic-gate load_propiter = NULL;
7960Sstevel@tonic-gate scf_iter_destroy(load_valiter);
7970Sstevel@tonic-gate load_valiter = NULL;
7987887SLiane.Praza@Sun.COM scf_iter_destroy(load_pgiter);
7997887SLiane.Praza@Sun.COM load_pgiter = NULL;
8007887SLiane.Praza@Sun.COM scf_pg_destroy(load_pgroup);
8017887SLiane.Praza@Sun.COM load_pgroup = NULL;
8020Sstevel@tonic-gate scf_value_destroy(load_val);
8030Sstevel@tonic-gate load_val = NULL;
8040Sstevel@tonic-gate scf_property_destroy(load_prop);
8050Sstevel@tonic-gate load_prop = NULL;
8060Sstevel@tonic-gate free(loadbuf);
8070Sstevel@tonic-gate loadbuf = NULL;
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate * Create a property_t which represents an scf_property_t. Returns
8120Sstevel@tonic-gate * 0 - success
8130Sstevel@tonic-gate * ECANCELED - prop's pg was deleted
8140Sstevel@tonic-gate * ECONNABORTED - repository disconnected
8150Sstevel@tonic-gate * ENOMEM - out of memory
8165040Swesolows * EACCES - permission denied when reading property
8170Sstevel@tonic-gate */
8180Sstevel@tonic-gate static int
load_property(scf_property_t * prop,property_t ** ipp)8190Sstevel@tonic-gate load_property(scf_property_t *prop, property_t **ipp)
8200Sstevel@tonic-gate {
8210Sstevel@tonic-gate property_t *iprop;
8220Sstevel@tonic-gate int r;
8230Sstevel@tonic-gate ssize_t ssz;
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate /* get name */
8260Sstevel@tonic-gate if (scf_property_get_name(prop, loadbuf, loadbuf_sz) < 0) {
8270Sstevel@tonic-gate switch (scf_error()) {
8280Sstevel@tonic-gate case SCF_ERROR_DELETED:
8290Sstevel@tonic-gate return (ECANCELED);
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
8320Sstevel@tonic-gate return (ECONNABORTED);
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
8350Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
8360Sstevel@tonic-gate default:
8370Sstevel@tonic-gate bad_error("scf_property_get_name", scf_error());
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate iprop = internal_property_new();
8420Sstevel@tonic-gate iprop->sc_property_name = strdup(loadbuf);
8430Sstevel@tonic-gate if (iprop->sc_property_name == NULL) {
8440Sstevel@tonic-gate internal_property_free(iprop);
8450Sstevel@tonic-gate return (ENOMEM);
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate /* get type */
8490Sstevel@tonic-gate if (scf_property_type(prop, &iprop->sc_value_type) != 0) {
8500Sstevel@tonic-gate switch (scf_error()) {
8510Sstevel@tonic-gate case SCF_ERROR_DELETED:
8520Sstevel@tonic-gate r = ECANCELED;
8530Sstevel@tonic-gate goto out;
8540Sstevel@tonic-gate
8550Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
8560Sstevel@tonic-gate r = ECONNABORTED;
8570Sstevel@tonic-gate goto out;
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
8600Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
8610Sstevel@tonic-gate default:
8620Sstevel@tonic-gate bad_error("scf_property_type", scf_error());
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate }
8650Sstevel@tonic-gate
8660Sstevel@tonic-gate /* get values */
8670Sstevel@tonic-gate if (scf_iter_property_values(load_valiter, prop) != 0) {
8680Sstevel@tonic-gate switch (scf_error()) {
8690Sstevel@tonic-gate case SCF_ERROR_DELETED:
8700Sstevel@tonic-gate r = ECANCELED;
8710Sstevel@tonic-gate goto out;
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
8740Sstevel@tonic-gate r = ECONNABORTED;
8750Sstevel@tonic-gate goto out;
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
8780Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
8790Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
8800Sstevel@tonic-gate default:
8810Sstevel@tonic-gate bad_error("scf_iter_property_values", scf_error());
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate
8850Sstevel@tonic-gate for (;;) {
8860Sstevel@tonic-gate value_t *ival;
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate r = scf_iter_next_value(load_valiter, load_val);
8890Sstevel@tonic-gate if (r == 0)
8900Sstevel@tonic-gate break;
8910Sstevel@tonic-gate if (r != 1) {
8920Sstevel@tonic-gate switch (scf_error()) {
8930Sstevel@tonic-gate case SCF_ERROR_DELETED:
8940Sstevel@tonic-gate r = ECANCELED;
8950Sstevel@tonic-gate goto out;
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
8980Sstevel@tonic-gate r = ECONNABORTED;
8990Sstevel@tonic-gate goto out;
9000Sstevel@tonic-gate
9015040Swesolows case SCF_ERROR_PERMISSION_DENIED:
9025040Swesolows r = EACCES;
9035040Swesolows goto out;
9045040Swesolows
9050Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
9060Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
9070Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
9080Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
9090Sstevel@tonic-gate default:
9100Sstevel@tonic-gate bad_error("scf_iter_next_value", scf_error());
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate }
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate ival = internal_value_new();
9150Sstevel@tonic-gate ival->sc_type = scf_value_type(load_val);
9160Sstevel@tonic-gate assert(ival->sc_type != SCF_TYPE_INVALID);
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate switch (ival->sc_type) {
9190Sstevel@tonic-gate case SCF_TYPE_BOOLEAN: {
9200Sstevel@tonic-gate uint8_t b;
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate r = scf_value_get_boolean(load_val, &b);
9230Sstevel@tonic-gate if (r != 0)
9240Sstevel@tonic-gate bad_error("scf_value_get_boolean", scf_error());
9250Sstevel@tonic-gate ival->sc_u.sc_count = b;
9260Sstevel@tonic-gate break;
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate case SCF_TYPE_COUNT:
9300Sstevel@tonic-gate r = scf_value_get_count(load_val, &ival->sc_u.sc_count);
9310Sstevel@tonic-gate if (r != 0)
9320Sstevel@tonic-gate bad_error("scf_value_get_count", scf_error());
9330Sstevel@tonic-gate break;
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate case SCF_TYPE_INTEGER:
9360Sstevel@tonic-gate r = scf_value_get_integer(load_val,
9370Sstevel@tonic-gate &ival->sc_u.sc_integer);
9380Sstevel@tonic-gate if (r != 0)
9390Sstevel@tonic-gate bad_error("scf_value_get_integer", scf_error());
9400Sstevel@tonic-gate break;
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate default:
9430Sstevel@tonic-gate ssz = scf_value_get_as_string(load_val, loadbuf,
9440Sstevel@tonic-gate loadbuf_sz);
9450Sstevel@tonic-gate if (ssz < 0)
9460Sstevel@tonic-gate bad_error("scf_value_get_as_string",
9470Sstevel@tonic-gate scf_error());
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate ival->sc_u.sc_string = strdup(loadbuf);
9500Sstevel@tonic-gate if (ival->sc_u.sc_string == NULL) {
9510Sstevel@tonic-gate r = ENOMEM;
9520Sstevel@tonic-gate goto out;
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate
9550Sstevel@tonic-gate ival->sc_free = internal_value_free_str;
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate internal_attach_value(iprop, ival);
9590Sstevel@tonic-gate }
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate *ipp = iprop;
9620Sstevel@tonic-gate return (0);
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate out:
9650Sstevel@tonic-gate free(iprop->sc_property_name);
9660Sstevel@tonic-gate internal_property_free(iprop);
9670Sstevel@tonic-gate return (r);
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate /*
9710Sstevel@tonic-gate * Returns
9720Sstevel@tonic-gate * 0 - success
9730Sstevel@tonic-gate * ECANCELED - pg was deleted
9740Sstevel@tonic-gate * ECONNABORTED - repository disconnected
9750Sstevel@tonic-gate * ENOMEM - out of memory
9760Sstevel@tonic-gate */
9770Sstevel@tonic-gate int
load_pg_attrs(const scf_propertygroup_t * pg,pgroup_t ** ipgp)9780Sstevel@tonic-gate load_pg_attrs(const scf_propertygroup_t *pg, pgroup_t **ipgp)
9790Sstevel@tonic-gate {
9800Sstevel@tonic-gate pgroup_t *ipg;
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate ipg = internal_pgroup_new();
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate if (scf_pg_get_flags(pg, &ipg->sc_pgroup_flags) != 0) {
9850Sstevel@tonic-gate switch (scf_error()) {
9860Sstevel@tonic-gate case SCF_ERROR_DELETED:
9870Sstevel@tonic-gate internal_pgroup_free(ipg);
9880Sstevel@tonic-gate return (ECANCELED);
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
9910Sstevel@tonic-gate internal_pgroup_free(ipg);
9920Sstevel@tonic-gate return (ECONNABORTED);
9930Sstevel@tonic-gate
9940Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
9950Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
9960Sstevel@tonic-gate default:
9970Sstevel@tonic-gate bad_error("scf_pg_get_name", scf_error());
9980Sstevel@tonic-gate }
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate
10010Sstevel@tonic-gate if (scf_pg_get_name(pg, loadbuf, loadbuf_sz) < 0) {
10020Sstevel@tonic-gate switch (scf_error()) {
10030Sstevel@tonic-gate case SCF_ERROR_DELETED:
10040Sstevel@tonic-gate internal_pgroup_free(ipg);
10050Sstevel@tonic-gate return (ECANCELED);
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
10080Sstevel@tonic-gate internal_pgroup_free(ipg);
10090Sstevel@tonic-gate return (ECONNABORTED);
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
10120Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
10130Sstevel@tonic-gate default:
10140Sstevel@tonic-gate bad_error("scf_pg_get_name", scf_error());
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate ipg->sc_pgroup_name = strdup(loadbuf);
10190Sstevel@tonic-gate if (ipg->sc_pgroup_name == NULL) {
10200Sstevel@tonic-gate internal_pgroup_free(ipg);
10210Sstevel@tonic-gate return (ENOMEM);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate if (scf_pg_get_type(pg, loadbuf, loadbuf_sz) < 0) {
10250Sstevel@tonic-gate switch (scf_error()) {
10260Sstevel@tonic-gate case SCF_ERROR_DELETED:
10270Sstevel@tonic-gate free((char *)ipg->sc_pgroup_name);
10280Sstevel@tonic-gate internal_pgroup_free(ipg);
10290Sstevel@tonic-gate return (ECANCELED);
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
10320Sstevel@tonic-gate free((char *)ipg->sc_pgroup_name);
10330Sstevel@tonic-gate internal_pgroup_free(ipg);
10340Sstevel@tonic-gate return (ECONNABORTED);
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
10370Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
10380Sstevel@tonic-gate default:
10390Sstevel@tonic-gate bad_error("scf_pg_get_name", scf_error());
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate }
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate ipg->sc_pgroup_type = strdup(loadbuf);
10440Sstevel@tonic-gate if (ipg->sc_pgroup_type == NULL) {
10450Sstevel@tonic-gate free((char *)ipg->sc_pgroup_name);
10460Sstevel@tonic-gate internal_pgroup_free(ipg);
10470Sstevel@tonic-gate return (ENOMEM);
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate
10500Sstevel@tonic-gate *ipgp = ipg;
10510Sstevel@tonic-gate return (0);
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /*
10550Sstevel@tonic-gate * Load a property group into a pgroup_t. Returns
10560Sstevel@tonic-gate * 0 - success
10570Sstevel@tonic-gate * ECANCELED - pg was deleted
10580Sstevel@tonic-gate * ECONNABORTED - repository disconnected
10590Sstevel@tonic-gate * EBADF - pg is corrupt (error printed if fmri is given)
10600Sstevel@tonic-gate * ENOMEM - out of memory
10615040Swesolows * EACCES - permission denied when reading property
10620Sstevel@tonic-gate */
10630Sstevel@tonic-gate int
load_pg(const scf_propertygroup_t * pg,pgroup_t ** ipgp,const char * fmri,const char * snapname)10640Sstevel@tonic-gate load_pg(const scf_propertygroup_t *pg, pgroup_t **ipgp, const char *fmri,
10650Sstevel@tonic-gate const char *snapname)
10660Sstevel@tonic-gate {
10670Sstevel@tonic-gate pgroup_t *ipg;
10680Sstevel@tonic-gate int r;
10690Sstevel@tonic-gate
10700Sstevel@tonic-gate if (scf_iter_pg_properties(load_propiter, pg) != 0) {
10710Sstevel@tonic-gate switch (scf_error()) {
10720Sstevel@tonic-gate case SCF_ERROR_DELETED:
10730Sstevel@tonic-gate return (ECANCELED);
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
10760Sstevel@tonic-gate return (ECONNABORTED);
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
10790Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
10800Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
10810Sstevel@tonic-gate default:
10820Sstevel@tonic-gate bad_error("scf_iter_pg_properties", scf_error());
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate }
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate r = load_pg_attrs(pg, &ipg);
10870Sstevel@tonic-gate switch (r) {
10880Sstevel@tonic-gate case 0:
10890Sstevel@tonic-gate break;
10900Sstevel@tonic-gate
10910Sstevel@tonic-gate case ECANCELED:
10920Sstevel@tonic-gate case ECONNABORTED:
10930Sstevel@tonic-gate case ENOMEM:
10940Sstevel@tonic-gate return (r);
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate default:
10970Sstevel@tonic-gate bad_error("load_pg_attrs", r);
10980Sstevel@tonic-gate }
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate for (;;) {
11010Sstevel@tonic-gate property_t *iprop;
11020Sstevel@tonic-gate
11030Sstevel@tonic-gate r = scf_iter_next_property(load_propiter, load_prop);
11040Sstevel@tonic-gate if (r == 0)
11050Sstevel@tonic-gate break;
11060Sstevel@tonic-gate if (r != 1) {
11070Sstevel@tonic-gate switch (scf_error()) {
11080Sstevel@tonic-gate case SCF_ERROR_DELETED:
11090Sstevel@tonic-gate r = ECANCELED;
11100Sstevel@tonic-gate goto out;
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
11130Sstevel@tonic-gate r = ECONNABORTED;
11140Sstevel@tonic-gate goto out;
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
11170Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
11180Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
11190Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
11200Sstevel@tonic-gate default:
11210Sstevel@tonic-gate bad_error("scf_iter_next_property",
11220Sstevel@tonic-gate scf_error());
11230Sstevel@tonic-gate }
11240Sstevel@tonic-gate }
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate r = load_property(load_prop, &iprop);
11270Sstevel@tonic-gate switch (r) {
11280Sstevel@tonic-gate case 0:
11290Sstevel@tonic-gate break;
11300Sstevel@tonic-gate
11310Sstevel@tonic-gate case ECANCELED:
11320Sstevel@tonic-gate case ECONNABORTED:
11330Sstevel@tonic-gate case ENOMEM:
11345040Swesolows case EACCES:
11350Sstevel@tonic-gate goto out;
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate default:
11380Sstevel@tonic-gate bad_error("load_property", r);
11390Sstevel@tonic-gate }
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate r = internal_attach_property(ipg, iprop);
11420Sstevel@tonic-gate if (r != 0) {
11430Sstevel@tonic-gate if (fmri != NULL) {
11440Sstevel@tonic-gate if (snapname == NULL)
11450Sstevel@tonic-gate warn(gettext("Property group \"%s\" of "
11460Sstevel@tonic-gate "%s has multiple definitions of "
11470Sstevel@tonic-gate "property \"%s\".\n"),
11480Sstevel@tonic-gate ipg->sc_pgroup_name, fmri,
11490Sstevel@tonic-gate iprop->sc_property_name);
11500Sstevel@tonic-gate else
11510Sstevel@tonic-gate warn(gettext("Property group \"%s\" of "
11520Sstevel@tonic-gate "the \"%s\" snapshot of %s has "
11530Sstevel@tonic-gate "multiple definitions of property "
11540Sstevel@tonic-gate "\"%s\".\n"),
11550Sstevel@tonic-gate ipg->sc_pgroup_name, snapname, fmri,
11560Sstevel@tonic-gate iprop->sc_property_name);
11570Sstevel@tonic-gate }
11580Sstevel@tonic-gate r = EBADF;
11590Sstevel@tonic-gate goto out;
11600Sstevel@tonic-gate }
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate *ipgp = ipg;
11640Sstevel@tonic-gate return (0);
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate out:
11670Sstevel@tonic-gate internal_pgroup_free(ipg);
11680Sstevel@tonic-gate return (r);
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate /*
11727887SLiane.Praza@Sun.COM * Load the instance for fmri from the repository into memory. The
11737887SLiane.Praza@Sun.COM * property groups that define the instances pg_patterns and prop_patterns
11747887SLiane.Praza@Sun.COM * are also loaded.
11757887SLiane.Praza@Sun.COM *
11767887SLiane.Praza@Sun.COM * Returns 0 on success and non-zero on failure.
11777887SLiane.Praza@Sun.COM */
11787887SLiane.Praza@Sun.COM int
load_instance(const char * fmri,const char * name,entity_t ** inst_ptr)11797887SLiane.Praza@Sun.COM load_instance(const char *fmri, const char *name, entity_t **inst_ptr)
11807887SLiane.Praza@Sun.COM {
11817887SLiane.Praza@Sun.COM entity_t *e = NULL;
11827887SLiane.Praza@Sun.COM scf_instance_t *inst;
11837887SLiane.Praza@Sun.COM pgroup_t *ipg;
11847887SLiane.Praza@Sun.COM int rc;
11857887SLiane.Praza@Sun.COM char *type = NULL;
11867887SLiane.Praza@Sun.COM ssize_t tsize;
11877887SLiane.Praza@Sun.COM
11887887SLiane.Praza@Sun.COM assert(inst_ptr != NULL);
11897887SLiane.Praza@Sun.COM
11907887SLiane.Praza@Sun.COM if ((inst = scf_instance_create(g_hndl)) == NULL) {
11917887SLiane.Praza@Sun.COM switch (scf_error()) {
11927887SLiane.Praza@Sun.COM case SCF_ERROR_NO_MEMORY:
11937887SLiane.Praza@Sun.COM case SCF_ERROR_NO_RESOURCES:
11947887SLiane.Praza@Sun.COM rc = EAGAIN;
11957887SLiane.Praza@Sun.COM goto errout;
11967887SLiane.Praza@Sun.COM default:
11977887SLiane.Praza@Sun.COM bad_error("scf_instance_create", scf_error());
11987887SLiane.Praza@Sun.COM }
11997887SLiane.Praza@Sun.COM }
12007887SLiane.Praza@Sun.COM if (scf_handle_decode_fmri(g_hndl, fmri, NULL, NULL, inst, NULL, NULL,
12017887SLiane.Praza@Sun.COM SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
12027887SLiane.Praza@Sun.COM switch (scf_error()) {
12037887SLiane.Praza@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
12047887SLiane.Praza@Sun.COM rc = ECONNABORTED;
12057887SLiane.Praza@Sun.COM goto errout;
12067887SLiane.Praza@Sun.COM case SCF_ERROR_DELETED:
12077887SLiane.Praza@Sun.COM case SCF_ERROR_NOT_FOUND:
12087887SLiane.Praza@Sun.COM rc = ENOENT;
12097887SLiane.Praza@Sun.COM goto errout;
12109765SSean.Wilcox@Sun.COM case SCF_ERROR_INVALID_ARGUMENT:
12119765SSean.Wilcox@Sun.COM rc = EINVAL;
12129765SSean.Wilcox@Sun.COM goto errout;
12139765SSean.Wilcox@Sun.COM case SCF_ERROR_CONSTRAINT_VIOLATED:
12149765SSean.Wilcox@Sun.COM rc = ENOTSUP;
12159765SSean.Wilcox@Sun.COM goto errout;
12167887SLiane.Praza@Sun.COM default:
12177887SLiane.Praza@Sun.COM bad_error("scf_handle_decode_fmri", scf_error());
12187887SLiane.Praza@Sun.COM }
12197887SLiane.Praza@Sun.COM }
12207887SLiane.Praza@Sun.COM if (scf_iter_instance_pgs_composed(load_pgiter, inst, NULL) != 0) {
12217887SLiane.Praza@Sun.COM switch (scf_error()) {
12227887SLiane.Praza@Sun.COM case SCF_ERROR_DELETED:
12237887SLiane.Praza@Sun.COM rc = ECANCELED;
12247887SLiane.Praza@Sun.COM goto errout;
12257887SLiane.Praza@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
12267887SLiane.Praza@Sun.COM rc = ECONNABORTED;
12277887SLiane.Praza@Sun.COM goto errout;
12287887SLiane.Praza@Sun.COM default:
12297887SLiane.Praza@Sun.COM bad_error("scf_iter_instance_pgs_composed",
12307887SLiane.Praza@Sun.COM scf_error());
12317887SLiane.Praza@Sun.COM }
12327887SLiane.Praza@Sun.COM }
12337887SLiane.Praza@Sun.COM
12347887SLiane.Praza@Sun.COM tsize = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH);
12357887SLiane.Praza@Sun.COM type = uu_zalloc(tsize);
12367887SLiane.Praza@Sun.COM if (type == NULL) {
12377887SLiane.Praza@Sun.COM rc = ENOMEM;
12387887SLiane.Praza@Sun.COM goto errout;
12397887SLiane.Praza@Sun.COM }
12407887SLiane.Praza@Sun.COM
12417887SLiane.Praza@Sun.COM /*
12427887SLiane.Praza@Sun.COM * Initialize our entity structure.
12437887SLiane.Praza@Sun.COM */
12447887SLiane.Praza@Sun.COM e = internal_instance_new(name);
12457887SLiane.Praza@Sun.COM if (e == NULL) {
12467887SLiane.Praza@Sun.COM rc = ENOMEM;
12477887SLiane.Praza@Sun.COM goto errout;
12487887SLiane.Praza@Sun.COM }
12497887SLiane.Praza@Sun.COM e->sc_fmri = uu_strdup(fmri);
12507887SLiane.Praza@Sun.COM if (e->sc_fmri == NULL) {
12517887SLiane.Praza@Sun.COM rc = ENOMEM;
12527887SLiane.Praza@Sun.COM goto errout;
12537887SLiane.Praza@Sun.COM }
12547887SLiane.Praza@Sun.COM
12557887SLiane.Praza@Sun.COM /*
12567887SLiane.Praza@Sun.COM * Walk through the property group's of the instance and capture
12577887SLiane.Praza@Sun.COM * the property groups that are of type
12587887SLiane.Praza@Sun.COM * SCF_GROUP_TEMPLATE_PG_PATTERN and
12597887SLiane.Praza@Sun.COM * SCF_GROUP_TEMPLATE_PROP_PATTERN. In other words grab the
12607887SLiane.Praza@Sun.COM * pg_pattern and prop_pattern property groups.
12617887SLiane.Praza@Sun.COM */
12627887SLiane.Praza@Sun.COM while ((rc = scf_iter_next_pg(load_pgiter, load_pgroup)) == 1) {
12637887SLiane.Praza@Sun.COM if (scf_pg_get_type(load_pgroup, type, tsize) <= 0) {
12647887SLiane.Praza@Sun.COM switch (scf_error()) {
12657887SLiane.Praza@Sun.COM case SCF_ERROR_DELETED:
12667887SLiane.Praza@Sun.COM rc = ENOENT;
12677887SLiane.Praza@Sun.COM break;
12687887SLiane.Praza@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
12697887SLiane.Praza@Sun.COM rc = ECONNABORTED;
12707887SLiane.Praza@Sun.COM break;
12717887SLiane.Praza@Sun.COM default:
12727887SLiane.Praza@Sun.COM bad_error("scf_pg_get_type", scf_error());
12737887SLiane.Praza@Sun.COM }
12747887SLiane.Praza@Sun.COM goto errout;
12757887SLiane.Praza@Sun.COM }
12767887SLiane.Praza@Sun.COM if ((strcmp(type, SCF_GROUP_TEMPLATE_PG_PATTERN) != 0) &&
12777887SLiane.Praza@Sun.COM (strcmp(type, SCF_GROUP_TEMPLATE_PROP_PATTERN) != 0)) {
12787887SLiane.Praza@Sun.COM continue;
12797887SLiane.Praza@Sun.COM }
12807887SLiane.Praza@Sun.COM if ((rc = load_pg(load_pgroup, &ipg, fmri, NULL)) != 0) {
12817887SLiane.Praza@Sun.COM switch (rc) {
12827887SLiane.Praza@Sun.COM case ECANCELED:
12837887SLiane.Praza@Sun.COM case ECONNABORTED:
12847887SLiane.Praza@Sun.COM case EACCES:
12857887SLiane.Praza@Sun.COM case ENOMEM:
12867887SLiane.Praza@Sun.COM break;
12877887SLiane.Praza@Sun.COM default:
12887887SLiane.Praza@Sun.COM bad_error("load_pg", rc);
12897887SLiane.Praza@Sun.COM }
12907887SLiane.Praza@Sun.COM goto errout;
12917887SLiane.Praza@Sun.COM }
12927887SLiane.Praza@Sun.COM if (internal_attach_pgroup(e, ipg) != 0) {
12937887SLiane.Praza@Sun.COM rc = EBADF;
12947887SLiane.Praza@Sun.COM goto errout;
12957887SLiane.Praza@Sun.COM }
12967887SLiane.Praza@Sun.COM }
12977887SLiane.Praza@Sun.COM if (rc == -1) {
12987887SLiane.Praza@Sun.COM /* Error in iteration. */
12997887SLiane.Praza@Sun.COM switch (scf_error()) {
13007887SLiane.Praza@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
13017887SLiane.Praza@Sun.COM rc = ECONNABORTED;
13027887SLiane.Praza@Sun.COM break;
13037887SLiane.Praza@Sun.COM case SCF_ERROR_DELETED:
13047887SLiane.Praza@Sun.COM rc = ENOENT;
13057887SLiane.Praza@Sun.COM break;
13067887SLiane.Praza@Sun.COM case SCF_ERROR_NO_RESOURCES:
13077887SLiane.Praza@Sun.COM rc = EAGAIN;
13087887SLiane.Praza@Sun.COM break;
13097887SLiane.Praza@Sun.COM default:
13107887SLiane.Praza@Sun.COM bad_error("scf_iter_next_pg", scf_error());
13117887SLiane.Praza@Sun.COM }
13127887SLiane.Praza@Sun.COM goto errout;
13137887SLiane.Praza@Sun.COM }
13147887SLiane.Praza@Sun.COM
13157887SLiane.Praza@Sun.COM *inst_ptr = e;
13167887SLiane.Praza@Sun.COM scf_instance_destroy(inst);
13177887SLiane.Praza@Sun.COM return (0);
13187887SLiane.Praza@Sun.COM
13197887SLiane.Praza@Sun.COM errout:
13207887SLiane.Praza@Sun.COM if (type != NULL)
13217887SLiane.Praza@Sun.COM uu_free(type);
13227887SLiane.Praza@Sun.COM if (inst != NULL)
13237887SLiane.Praza@Sun.COM scf_instance_destroy(inst);
13247887SLiane.Praza@Sun.COM if (e != NULL)
13257887SLiane.Praza@Sun.COM internal_instance_free(e);
13267887SLiane.Praza@Sun.COM return (rc);
13277887SLiane.Praza@Sun.COM }
13287887SLiane.Praza@Sun.COM
13297887SLiane.Praza@Sun.COM /*
13300Sstevel@tonic-gate * These functions compare internal property groups and properties (pgroup_t
13310Sstevel@tonic-gate * & property_t). They return 1 if the given structures are equal and
13320Sstevel@tonic-gate * 0 otherwise. Some will report the differences between the two structures.
13330Sstevel@tonic-gate * They are used by the import functions in svccfg_libscf.c .
13340Sstevel@tonic-gate */
13350Sstevel@tonic-gate
13360Sstevel@tonic-gate int
prop_equal(property_t * p1,property_t * p2,const char * fmri,const char * pgname,int new)13370Sstevel@tonic-gate prop_equal(property_t *p1, property_t *p2, const char *fmri, const char *pgname,
13380Sstevel@tonic-gate int new)
13390Sstevel@tonic-gate {
13400Sstevel@tonic-gate value_t *v1, *v2;
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate const char * const values_diff = gettext("Conflict upgrading %s "
13430Sstevel@tonic-gate "(property \"%s/%s\" has different values).\n");
13440Sstevel@tonic-gate const char * const values_diff_new = gettext("Conflict upgrading %s "
13450Sstevel@tonic-gate "(new property \"%s/%s\" has different values).\n");
13460Sstevel@tonic-gate
13470Sstevel@tonic-gate assert((fmri == NULL) == (pgname == NULL));
13480Sstevel@tonic-gate
13490Sstevel@tonic-gate if (fmri != NULL) {
13500Sstevel@tonic-gate /*
13510Sstevel@tonic-gate * If we find any differences, we'll report conflicts. But
13520Sstevel@tonic-gate * conflict messages won't make any sense if the names don't
13530Sstevel@tonic-gate * match. If the caller supplied fmri, assert that the names
13540Sstevel@tonic-gate * match.
13550Sstevel@tonic-gate */
13560Sstevel@tonic-gate assert(strcmp(p1->sc_property_name, p2->sc_property_name) == 0);
13570Sstevel@tonic-gate } else {
13580Sstevel@tonic-gate if (strcmp(p1->sc_property_name, p2->sc_property_name) != 0)
13590Sstevel@tonic-gate return (0);
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate
13620Sstevel@tonic-gate if (p1->sc_value_type != p2->sc_value_type) {
13630Sstevel@tonic-gate if (fmri != NULL) {
13640Sstevel@tonic-gate if (new)
13650Sstevel@tonic-gate warn(gettext("Conflict upgrading %s "
13660Sstevel@tonic-gate "(new property \"%s/%s\" has different "
13670Sstevel@tonic-gate "type).\n"), fmri, pgname,
13680Sstevel@tonic-gate p1->sc_property_name);
13690Sstevel@tonic-gate else
13700Sstevel@tonic-gate warn(gettext("Conflict upgrading %s "
13710Sstevel@tonic-gate "(property \"%s/%s\" has different "
13720Sstevel@tonic-gate "type).\n"), fmri, pgname,
13730Sstevel@tonic-gate p1->sc_property_name);
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate return (0);
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate
13780Sstevel@tonic-gate if (uu_list_numnodes(p1->sc_property_values) !=
13790Sstevel@tonic-gate uu_list_numnodes(p2->sc_property_values)) {
13800Sstevel@tonic-gate if (fmri != NULL)
13810Sstevel@tonic-gate warn(new ? values_diff_new : values_diff, fmri,
13820Sstevel@tonic-gate pgname, p1->sc_property_name);
13830Sstevel@tonic-gate return (0);
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate
13860Sstevel@tonic-gate v1 = uu_list_first(p1->sc_property_values);
13870Sstevel@tonic-gate v2 = uu_list_first(p2->sc_property_values);
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate while (v1 != NULL) {
13900Sstevel@tonic-gate assert(v2 != NULL);
13910Sstevel@tonic-gate
13920Sstevel@tonic-gate if (value_cmp(v1, v2, NULL) != 0) {
13930Sstevel@tonic-gate if (fmri != NULL)
13940Sstevel@tonic-gate warn(new ? values_diff_new : values_diff,
13950Sstevel@tonic-gate fmri, pgname, p1->sc_property_name);
13960Sstevel@tonic-gate return (0);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate v1 = uu_list_next(p1->sc_property_values, v1);
14000Sstevel@tonic-gate v2 = uu_list_next(p2->sc_property_values, v2);
14010Sstevel@tonic-gate }
14020Sstevel@tonic-gate
14030Sstevel@tonic-gate return (1);
14040Sstevel@tonic-gate }
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate int
pg_attrs_equal(const pgroup_t * pg1,const pgroup_t * pg2,const char * fmri,int new)1407306Sbustos pg_attrs_equal(const pgroup_t *pg1, const pgroup_t *pg2, const char *fmri,
1408306Sbustos int new)
14090Sstevel@tonic-gate {
14100Sstevel@tonic-gate if (strcmp(pg1->sc_pgroup_name, pg2->sc_pgroup_name) != 0) {
14110Sstevel@tonic-gate assert(fmri == NULL);
14120Sstevel@tonic-gate return (0);
14130Sstevel@tonic-gate }
14140Sstevel@tonic-gate
14150Sstevel@tonic-gate if (pg1->sc_pgroup_flags != pg2->sc_pgroup_flags) {
14160Sstevel@tonic-gate if (fmri) {
14170Sstevel@tonic-gate if (new)
14180Sstevel@tonic-gate warn(gettext("Conflict upgrading %s "
14190Sstevel@tonic-gate "(new property group \"%s\" has different "
14200Sstevel@tonic-gate "flags).\n"), fmri, pg1->sc_pgroup_name);
14210Sstevel@tonic-gate else
14220Sstevel@tonic-gate warn(gettext("Conflict upgrading %s "
14230Sstevel@tonic-gate "(property group \"%s\" has different "
14240Sstevel@tonic-gate "flags).\n"), fmri, pg1->sc_pgroup_name);
14250Sstevel@tonic-gate }
14260Sstevel@tonic-gate return (0);
14270Sstevel@tonic-gate }
14280Sstevel@tonic-gate
14290Sstevel@tonic-gate if (strcmp(pg1->sc_pgroup_type, pg2->sc_pgroup_type) != 0) {
14300Sstevel@tonic-gate if (fmri) {
14310Sstevel@tonic-gate if (new)
14320Sstevel@tonic-gate warn(gettext("Conflict upgrading %s "
14330Sstevel@tonic-gate "(new property group \"%s\" has different "
14340Sstevel@tonic-gate "type).\n"), fmri, pg1->sc_pgroup_name);
14350Sstevel@tonic-gate else
14360Sstevel@tonic-gate warn(gettext("Conflict upgrading %s "
14370Sstevel@tonic-gate "(property group \"%s\" has different "
14380Sstevel@tonic-gate "type).\n"), fmri, pg1->sc_pgroup_name);
14390Sstevel@tonic-gate }
14400Sstevel@tonic-gate return (0);
14410Sstevel@tonic-gate }
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate return (1);
14440Sstevel@tonic-gate }
14450Sstevel@tonic-gate
14460Sstevel@tonic-gate int
pg_equal(pgroup_t * pg1,pgroup_t * pg2)14470Sstevel@tonic-gate pg_equal(pgroup_t *pg1, pgroup_t *pg2)
14480Sstevel@tonic-gate {
14490Sstevel@tonic-gate property_t *p1, *p2;
14500Sstevel@tonic-gate
14510Sstevel@tonic-gate if (!pg_attrs_equal(pg1, pg2, NULL, 0))
14520Sstevel@tonic-gate return (0);
14530Sstevel@tonic-gate
14540Sstevel@tonic-gate if (uu_list_numnodes(pg1->sc_pgroup_props) !=
14550Sstevel@tonic-gate uu_list_numnodes(pg2->sc_pgroup_props))
14560Sstevel@tonic-gate return (0);
14570Sstevel@tonic-gate
14580Sstevel@tonic-gate p1 = uu_list_first(pg1->sc_pgroup_props);
14590Sstevel@tonic-gate p2 = uu_list_first(pg2->sc_pgroup_props);
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate while (p1 != NULL) {
14620Sstevel@tonic-gate assert(p2 != NULL);
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate if (!prop_equal(p1, p2, NULL, NULL, 0))
14650Sstevel@tonic-gate return (0);
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate p1 = uu_list_next(pg1->sc_pgroup_props, p1);
14680Sstevel@tonic-gate p2 = uu_list_next(pg2->sc_pgroup_props, p2);
14690Sstevel@tonic-gate }
14700Sstevel@tonic-gate
14710Sstevel@tonic-gate return (1);
14720Sstevel@tonic-gate }
1473