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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 * 2721f6eb021SLiane Praza internal_entity_new(entity_type_t entity) 2731f6eb021SLiane Praza { 2741f6eb021SLiane Praza entity_t *e; 2751f6eb021SLiane Praza 2761f6eb021SLiane Praza if ((e = uu_zalloc(sizeof (entity_t))) == NULL) 2771f6eb021SLiane Praza uu_die(gettext("couldn't allocate memory")); 2781f6eb021SLiane Praza 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 * 2937c478bd9Sstevel@tonic-gate internal_service_new(const char *name) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate entity_t *s; 2967c478bd9Sstevel@tonic-gate 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 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 * 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 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 * 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 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 * 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 * 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 * 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 * 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 { 4717c478bd9Sstevel@tonic-gate 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 * 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 * 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 * 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 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 * 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 * 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 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 * 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 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 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 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 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 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 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 7337c478bd9Sstevel@tonic-gate void 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 7391f6eb021SLiane Praza void 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 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 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 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 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 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 11717c478bd9Sstevel@tonic-gate /* 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 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 13291f6eb021SLiane Praza /* 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 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 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 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