11f6eb021SLiane Praza /* 21f6eb021SLiane Praza * CDDL HEADER START 31f6eb021SLiane Praza * 41f6eb021SLiane Praza * The contents of this file are subject to the terms of the 51f6eb021SLiane Praza * Common Development and Distribution License (the "License"). 61f6eb021SLiane Praza * You may not use this file except in compliance with the License. 71f6eb021SLiane Praza * 81f6eb021SLiane Praza * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91f6eb021SLiane Praza * or http://www.opensolaris.org/os/licensing. 101f6eb021SLiane Praza * See the License for the specific language governing permissions 111f6eb021SLiane Praza * and limitations under the License. 121f6eb021SLiane Praza * 131f6eb021SLiane Praza * When distributing Covered Code, include this CDDL HEADER in each 141f6eb021SLiane Praza * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151f6eb021SLiane Praza * If applicable, add the following below this CDDL HEADER, with the 161f6eb021SLiane Praza * fields enclosed by brackets "[]" replaced with your own identifying 171f6eb021SLiane Praza * information: Portions Copyright [yyyy] [name of copyright owner] 181f6eb021SLiane Praza * 191f6eb021SLiane Praza * CDDL HEADER END 201f6eb021SLiane Praza */ 211f6eb021SLiane Praza /* 22f6e214c7SGavin Maltby * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23*a58a7fedSMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 241f6eb021SLiane Praza */ 251f6eb021SLiane Praza 261f6eb021SLiane Praza /* 271f6eb021SLiane Praza * scf_tmpl.c 281f6eb021SLiane Praza * 291f6eb021SLiane Praza * This file implements the bulk of the libscf templates interfaces. 301f6eb021SLiane Praza * Templates describe metadata about a service or instance in general, 311f6eb021SLiane Praza * and individual configuration properties on those services and instances. 321f6eb021SLiane Praza * Human-consumable descriptions can be provided, along with definitions 331f6eb021SLiane Praza * of valid configuration. See service_bundle.dtd.1 for XML definitions 341f6eb021SLiane Praza * of templates, and the svccfg code for information on how those definitions 351f6eb021SLiane Praza * are translated into the repository. 361f6eb021SLiane Praza * 371f6eb021SLiane Praza * The main data structures are scf_pg_tmpl and scf_prop_tmpl. These 381f6eb021SLiane Praza * are allocated by the callers through scf_tmpl_[pg|prop]_create(), and 391f6eb021SLiane Praza * destroyed with scf_tmpl_[pg|prop]_destroy(). They are populated by 401f6eb021SLiane Praza * scf_tmpl_get_by_pg_name(), scf_tmpl_get_by_pg(), and 411f6eb021SLiane Praza * scf_tmpl_get_by_prop(). They also store the iterator state for 421f6eb021SLiane Praza * scf_tmpl_iter_pgs() and scf_tmpl_iter_props(). 431f6eb021SLiane Praza * 441f6eb021SLiane Praza * These data structures are then consumed by other functions to 451f6eb021SLiane Praza * gather information about the template (e.g. name, description, 461f6eb021SLiane Praza * choices, constraints, etc.). 471f6eb021SLiane Praza * 481f6eb021SLiane Praza * scf_tmpl_validate_fmri() does instance validation against template 491f6eb021SLiane Praza * data, and populates a set of template errors which can be explored using 501f6eb021SLiane Praza * the scf_tmpl_next_error() and the scf_tmpl_error*() suite of functions. 511f6eb021SLiane Praza * 521f6eb021SLiane Praza * The main data structures for template errors are scf_tmpl_errors, 531f6eb021SLiane Praza * defined in this file, and scf_tmpl_error, defined in libscf_priv.h. 541f6eb021SLiane Praza * scf_tmpl_error is shared with svccfg to offer common printing 551f6eb021SLiane Praza * of error messages between libscf and svccfg. 561f6eb021SLiane Praza * 571f6eb021SLiane Praza * General convenience functions are towards the top of this file, 581f6eb021SLiane Praza * followed by pg and prop template discovery functions, followed 591f6eb021SLiane Praza * by functions which gather information about the discovered 601f6eb021SLiane Praza * template. Validation and error functions are at the end of this file. 611f6eb021SLiane Praza */ 621f6eb021SLiane Praza 631f6eb021SLiane Praza #include "lowlevel_impl.h" 641f6eb021SLiane Praza #include "libscf_impl.h" 651f6eb021SLiane Praza #include <assert.h> 661f6eb021SLiane Praza #include <errno.h> 671f6eb021SLiane Praza #include <libintl.h> 681f6eb021SLiane Praza #include <stdlib.h> 691f6eb021SLiane Praza #include <stdio.h> 701f6eb021SLiane Praza #include <strings.h> 711f6eb021SLiane Praza #include <locale.h> 721f6eb021SLiane Praza #include <ctype.h> 731f6eb021SLiane Praza #include <inttypes.h> 741f6eb021SLiane Praza 751f6eb021SLiane Praza #define SCF_TMPL_PG_COMMON_NAME_C "common_name_C" 761f6eb021SLiane Praza 771f6eb021SLiane Praza #define SCF__TMPL_ITER_NONE 0 781f6eb021SLiane Praza #define SCF__TMPL_ITER_INST 1 791f6eb021SLiane Praza #define SCF__TMPL_ITER_RESTARTER 2 801f6eb021SLiane Praza #define SCF__TMPL_ITER_GLOBAL 3 811f6eb021SLiane Praza 821f6eb021SLiane Praza #define SCF_TMPL_PG_NT 0 831f6eb021SLiane Praza #define SCF_TMPL_PG_N 1 841f6eb021SLiane Praza #define SCF_TMPL_PG_T 2 851f6eb021SLiane Praza #define SCF_TMPL_PG_WILD 3 861f6eb021SLiane Praza 871f6eb021SLiane Praza struct scf_pg_tmpl { 881f6eb021SLiane Praza int pt_populated; 891f6eb021SLiane Praza scf_handle_t *pt_h; 901f6eb021SLiane Praza scf_propertygroup_t *pt_pg; 911f6eb021SLiane Praza scf_service_t *pt_orig_svc; 921f6eb021SLiane Praza scf_service_t *pt_svc; 931f6eb021SLiane Praza scf_instance_t *pt_orig_inst; 941f6eb021SLiane Praza scf_instance_t *pt_inst; 951f6eb021SLiane Praza scf_snapshot_t *pt_snap; 961f6eb021SLiane Praza int pt_is_iter; 971f6eb021SLiane Praza scf_iter_t *pt_iter; 981f6eb021SLiane Praza int pt_iter_last; 991f6eb021SLiane Praza }; 1001f6eb021SLiane Praza 1011f6eb021SLiane Praza #define SCF_WALK_ERROR -1 1021f6eb021SLiane Praza #define SCF_WALK_NEXT 0 1031f6eb021SLiane Praza #define SCF_WALK_DONE 1 1041f6eb021SLiane Praza 1051f6eb021SLiane Praza struct pg_tmpl_walk { 1061f6eb021SLiane Praza const char *pw_snapname; 1071f6eb021SLiane Praza const char *pw_pgname; 1081f6eb021SLiane Praza const char *pw_pgtype; 1091f6eb021SLiane Praza scf_instance_t *pw_inst; 1101f6eb021SLiane Praza scf_service_t *pw_svc; 1111f6eb021SLiane Praza scf_snapshot_t *pw_snap; 1121f6eb021SLiane Praza scf_propertygroup_t *pw_pg; 1131f6eb021SLiane Praza const char *pw_target; 1141f6eb021SLiane Praza char *pw_tmpl_pgname; 1151f6eb021SLiane Praza }; 1161f6eb021SLiane Praza 1171f6eb021SLiane Praza typedef struct pg_tmpl_walk pg_tmpl_walk_t; 1181f6eb021SLiane Praza 1191f6eb021SLiane Praza typedef int walk_template_inst_func_t(scf_service_t *_svc, 1201f6eb021SLiane Praza scf_instance_t *_inst, pg_tmpl_walk_t *p); 1211f6eb021SLiane Praza 1221f6eb021SLiane Praza struct scf_prop_tmpl { 1231f6eb021SLiane Praza int prt_populated; 1241f6eb021SLiane Praza scf_handle_t *prt_h; 1251f6eb021SLiane Praza scf_pg_tmpl_t *prt_t; 1261f6eb021SLiane Praza scf_propertygroup_t *prt_pg; 1271f6eb021SLiane Praza char *prt_pg_name; 1281f6eb021SLiane Praza scf_iter_t *prt_iter; 1291f6eb021SLiane Praza }; 1301f6eb021SLiane Praza 1311f6eb021SLiane Praza /* 1321f6eb021SLiane Praza * Common server errors are usually passed back to the caller. This 1331f6eb021SLiane Praza * array defines them centrally so that they don't need to be enumerated 1341f6eb021SLiane Praza * in every libscf call. 1351f6eb021SLiane Praza */ 1361f6eb021SLiane Praza static const scf_error_t errors_server[] = { 1371f6eb021SLiane Praza SCF_ERROR_BACKEND_ACCESS, 1381f6eb021SLiane Praza SCF_ERROR_CONNECTION_BROKEN, 1391f6eb021SLiane Praza SCF_ERROR_DELETED, 1401f6eb021SLiane Praza SCF_ERROR_HANDLE_DESTROYED, 1411f6eb021SLiane Praza SCF_ERROR_INTERNAL, 1421f6eb021SLiane Praza SCF_ERROR_NO_MEMORY, 1431f6eb021SLiane Praza SCF_ERROR_NO_RESOURCES, 1441f6eb021SLiane Praza SCF_ERROR_NOT_BOUND, 1451f6eb021SLiane Praza SCF_ERROR_PERMISSION_DENIED, 1461f6eb021SLiane Praza 0 1471f6eb021SLiane Praza }; 1481f6eb021SLiane Praza 1491f6eb021SLiane Praza /* 1501f6eb021SLiane Praza * int ismember() 1511f6eb021SLiane Praza * 1521f6eb021SLiane Praza * Returns 1 if the supplied error is a member of the error array, 0 1531f6eb021SLiane Praza * if it is not. 1541f6eb021SLiane Praza */ 155f6e214c7SGavin Maltby int 156f6e214c7SGavin Maltby ismember(const scf_error_t error, const scf_error_t error_array[]) 1571f6eb021SLiane Praza { 1581f6eb021SLiane Praza int i; 1591f6eb021SLiane Praza 1601f6eb021SLiane Praza for (i = 0; error_array[i] != 0; ++i) { 1611f6eb021SLiane Praza if (error == error_array[i]) 1621f6eb021SLiane Praza return (1); 1631f6eb021SLiane Praza } 1641f6eb021SLiane Praza 1651f6eb021SLiane Praza return (0); 1661f6eb021SLiane Praza } 1671f6eb021SLiane Praza 1681f6eb021SLiane Praza /* 1691f6eb021SLiane Praza * char *_scf_tmpl_get_fmri() 1701f6eb021SLiane Praza * 1711f6eb021SLiane Praza * Given a pg_tmpl, returns the FMRI of the service or instance that 1721f6eb021SLiane Praza * template describes. The allocated string must be freed with free(). 1731f6eb021SLiane Praza * 1741f6eb021SLiane Praza * On failure, returns NULL and sets scf_error() to _CONNECTION_BROKEN, 1751f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 1761f6eb021SLiane Praza */ 1771f6eb021SLiane Praza static char * 1781f6eb021SLiane Praza _scf_tmpl_get_fmri(const scf_pg_tmpl_t *t) 1791f6eb021SLiane Praza { 1801f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1; 1811f6eb021SLiane Praza int r; 1821f6eb021SLiane Praza char *buf = malloc(sz); 1831f6eb021SLiane Praza 1841f6eb021SLiane Praza assert(t->pt_svc != NULL || t->pt_inst != NULL); 1851f6eb021SLiane Praza assert(t->pt_svc == NULL || t->pt_inst == NULL); 1861f6eb021SLiane Praza 1871f6eb021SLiane Praza if (buf == NULL) { 1881f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1891f6eb021SLiane Praza return (buf); 1901f6eb021SLiane Praza } 1911f6eb021SLiane Praza 1921f6eb021SLiane Praza if (t->pt_inst != NULL) 1931f6eb021SLiane Praza r = scf_instance_to_fmri(t->pt_inst, buf, sz); 1941f6eb021SLiane Praza else 1951f6eb021SLiane Praza r = scf_service_to_fmri(t->pt_svc, buf, sz); 1961f6eb021SLiane Praza 1971f6eb021SLiane Praza if (r == -1) { 1981f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1991f6eb021SLiane Praza free(buf); 2001f6eb021SLiane Praza buf = NULL; 2011f6eb021SLiane Praza } else { 2021f6eb021SLiane Praza assert(0); 2031f6eb021SLiane Praza abort(); 2041f6eb021SLiane Praza } 2051f6eb021SLiane Praza } 2061f6eb021SLiane Praza 2071f6eb021SLiane Praza return (buf); 2081f6eb021SLiane Praza } 2091f6eb021SLiane Praza 2101f6eb021SLiane Praza /* 2111f6eb021SLiane Praza * char *_scf_get_pg_type() 2121f6eb021SLiane Praza * 2131f6eb021SLiane Praza * Given a propertygroup, returns an allocated string containing the 2141f6eb021SLiane Praza * type. The string must be freed with free(). 2151f6eb021SLiane Praza * 2161f6eb021SLiane Praza * On failure, returns NULL and sets scf_error() to: _CONNECTION_BROKEN, 2171f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 2181f6eb021SLiane Praza */ 2191f6eb021SLiane Praza static char * 2201f6eb021SLiane Praza _scf_get_pg_type(scf_propertygroup_t *pg) 2211f6eb021SLiane Praza { 2221f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1; 2231f6eb021SLiane Praza char *buf = malloc(sz); 2241f6eb021SLiane Praza 2251f6eb021SLiane Praza if (buf == NULL) { 2261f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2271f6eb021SLiane Praza } else if (scf_pg_get_type(pg, buf, sz) == -1) { 2281f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2291f6eb021SLiane Praza free(buf); 2301f6eb021SLiane Praza buf = NULL; 2311f6eb021SLiane Praza } else { 2321f6eb021SLiane Praza assert(0); 2331f6eb021SLiane Praza abort(); 2341f6eb021SLiane Praza } 2351f6eb021SLiane Praza } 2361f6eb021SLiane Praza 2371f6eb021SLiane Praza return (buf); 2381f6eb021SLiane Praza } 2391f6eb021SLiane Praza 2401f6eb021SLiane Praza /* 2411f6eb021SLiane Praza * char *_scf_get_prop_name() 2421f6eb021SLiane Praza * 2431f6eb021SLiane Praza * Given a property, returns the name in an allocated string. The string must 2441f6eb021SLiane Praza * be freed with free(). 2451f6eb021SLiane Praza * 2461f6eb021SLiane Praza * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN, 2471f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 2481f6eb021SLiane Praza */ 2491f6eb021SLiane Praza static char * 2501f6eb021SLiane Praza _scf_get_prop_name(scf_property_t *prop) 2511f6eb021SLiane Praza { 2521f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 2531f6eb021SLiane Praza char *buf = malloc(sz); 2541f6eb021SLiane Praza 2551f6eb021SLiane Praza if (buf == NULL) { 2561f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2571f6eb021SLiane Praza } else if (scf_property_get_name(prop, buf, sz) == -1) { 2581f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2591f6eb021SLiane Praza free(buf); 2601f6eb021SLiane Praza buf = NULL; 2611f6eb021SLiane Praza } else { 2621f6eb021SLiane Praza assert(0); 2631f6eb021SLiane Praza abort(); 2641f6eb021SLiane Praza } 2651f6eb021SLiane Praza } 2661f6eb021SLiane Praza 2671f6eb021SLiane Praza return (buf); 2681f6eb021SLiane Praza } 2691f6eb021SLiane Praza 2701f6eb021SLiane Praza /* 2711f6eb021SLiane Praza * char *_scf_get_prop_type() 2721f6eb021SLiane Praza * 2731f6eb021SLiane Praza * Given a property, returns the type in an allocated string. The string must 2741f6eb021SLiane Praza * be freed with free(). 2751f6eb021SLiane Praza * 2761f6eb021SLiane Praza * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN, 2771f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 2781f6eb021SLiane Praza */ 2791f6eb021SLiane Praza static char * 2801f6eb021SLiane Praza _scf_get_prop_type(scf_property_t *prop) 2811f6eb021SLiane Praza { 2821f6eb021SLiane Praza scf_type_t type; 2831f6eb021SLiane Praza char *ret; 2841f6eb021SLiane Praza 2851f6eb021SLiane Praza if (scf_property_type(prop, &type) == -1) { 2861f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2871f6eb021SLiane Praza return (NULL); 2881f6eb021SLiane Praza } else { 2891f6eb021SLiane Praza assert(0); 2901f6eb021SLiane Praza abort(); 2911f6eb021SLiane Praza } 2921f6eb021SLiane Praza } 2931f6eb021SLiane Praza 2941f6eb021SLiane Praza ret = strdup(scf_type_to_string(type)); 2951f6eb021SLiane Praza if (ret == NULL) 2961f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2971f6eb021SLiane Praza 2981f6eb021SLiane Praza return (ret); 2991f6eb021SLiane Praza } 3001f6eb021SLiane Praza 3011f6eb021SLiane Praza /* 3021f6eb021SLiane Praza * int _read_single_value_from_pg() 3031f6eb021SLiane Praza * 3041f6eb021SLiane Praza * Reads a single value from the pg and property name specified. On success, 3051f6eb021SLiane Praza * returns an allocated value that must be freed. 3061f6eb021SLiane Praza * 3071f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 3081f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3091f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3101f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 3111f6eb021SLiane Praza * Property has more than one value associated with it. 3121f6eb021SLiane Praza * SCF_ERROR_DELETED 3131f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3141f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3151f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 3161f6eb021SLiane Praza * prop_name not a valid property name. 3171f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3181f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3191f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3201f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3211f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3221f6eb021SLiane Praza * SCF_ERROR_NOT_SET 3231f6eb021SLiane Praza * Property group specified by pg is not set. 3241f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3251f6eb021SLiane Praza */ 3261f6eb021SLiane Praza static int 3271f6eb021SLiane Praza _read_single_value_from_pg(scf_propertygroup_t *pg, const char *prop_name, 3281f6eb021SLiane Praza scf_value_t **val) 3291f6eb021SLiane Praza { 3301f6eb021SLiane Praza scf_handle_t *h; 3311f6eb021SLiane Praza scf_property_t *prop; 3321f6eb021SLiane Praza int ret = 0; 3331f6eb021SLiane Praza 3341f6eb021SLiane Praza assert(val != NULL); 3351f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) { 3361f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 3371f6eb021SLiane Praza return (-1); 3381f6eb021SLiane Praza } 3391f6eb021SLiane Praza 3401f6eb021SLiane Praza prop = scf_property_create(h); 3411f6eb021SLiane Praza *val = scf_value_create(h); 3421f6eb021SLiane Praza 3431f6eb021SLiane Praza if (prop == NULL || *val == NULL) { 3441f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 3451f6eb021SLiane Praza goto read_single_value_from_pg_fail; 3461f6eb021SLiane Praza } 3471f6eb021SLiane Praza 3481f6eb021SLiane Praza if (scf_pg_get_property(pg, prop_name, prop) != 0) { 3491f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 3501f6eb021SLiane Praza goto read_single_value_from_pg_fail; 3511f6eb021SLiane Praza } 3521f6eb021SLiane Praza 3531f6eb021SLiane Praza if (scf_property_get_value(prop, *val) == -1) { 3541f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 3551f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 3561f6eb021SLiane Praza goto read_single_value_from_pg_fail; 3571f6eb021SLiane Praza } 3581f6eb021SLiane Praza 3591f6eb021SLiane Praza goto read_single_value_from_pg_done; 3601f6eb021SLiane Praza 3611f6eb021SLiane Praza read_single_value_from_pg_fail: 3621f6eb021SLiane Praza scf_value_destroy(*val); 3631f6eb021SLiane Praza *val = NULL; 3641f6eb021SLiane Praza ret = -1; 3651f6eb021SLiane Praza 3661f6eb021SLiane Praza read_single_value_from_pg_done: 3671f6eb021SLiane Praza scf_property_destroy(prop); 3681f6eb021SLiane Praza return (ret); 3691f6eb021SLiane Praza } 3701f6eb021SLiane Praza 3711f6eb021SLiane Praza /* 3721f6eb021SLiane Praza * char *_scf_read_single_astring_from_pg() 3731f6eb021SLiane Praza * 3741f6eb021SLiane Praza * Reads an astring from the pg and property name specified. On success, 3751f6eb021SLiane Praza * returns an allocated string. The string must be freed with free(). 3761f6eb021SLiane Praza * 3771f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 3781f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3791f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3801f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 3811f6eb021SLiane Praza * Property has more than one value associated with it. 3821f6eb021SLiane Praza * SCF_ERROR_DELETED 3831f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3841f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3851f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 3861f6eb021SLiane Praza * prop_name not a valid property name. 3871f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3881f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3891f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3901f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3911f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3921f6eb021SLiane Praza * SCF_ERROR_NOT_SET 3931f6eb021SLiane Praza * The property group specified by pg is not set. 3941f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3951f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 3961f6eb021SLiane Praza */ 3971f6eb021SLiane Praza char * 3981f6eb021SLiane Praza _scf_read_single_astring_from_pg(scf_propertygroup_t *pg, const char *prop_name) 3991f6eb021SLiane Praza { 4001f6eb021SLiane Praza scf_value_t *val; 4011f6eb021SLiane Praza char *ret = NULL; 4021f6eb021SLiane Praza ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 4031f6eb021SLiane Praza 4041f6eb021SLiane Praza assert(rsize != 0); 4051f6eb021SLiane Praza if (_read_single_value_from_pg(pg, prop_name, &val) == -1) 4061f6eb021SLiane Praza return (NULL); 4071f6eb021SLiane Praza 4081f6eb021SLiane Praza ret = malloc(rsize); 4091f6eb021SLiane Praza if (ret == NULL) { 4101f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4111f6eb021SLiane Praza goto cleanup; 4121f6eb021SLiane Praza } 4131f6eb021SLiane Praza 4141f6eb021SLiane Praza if (scf_value_get_astring(val, ret, rsize) < 0) { 4151f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 4161f6eb021SLiane Praza free(ret); 4171f6eb021SLiane Praza ret = NULL; 4181f6eb021SLiane Praza } 4191f6eb021SLiane Praza 4201f6eb021SLiane Praza cleanup: 4211f6eb021SLiane Praza scf_value_destroy(val); 4221f6eb021SLiane Praza return (ret); 4231f6eb021SLiane Praza } 4241f6eb021SLiane Praza 4251f6eb021SLiane Praza /* 4261f6eb021SLiane Praza * char *_scf_read_tmpl_prop_type_as_string() 4271f6eb021SLiane Praza * 4281f6eb021SLiane Praza * Reads the property type and returns it as an allocated string. The string 4291f6eb021SLiane Praza * must be freed with free(). 4301f6eb021SLiane Praza * 4311f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _BACKEND_ACCESS, 4321f6eb021SLiane Praza * _CONNECTION_BROKEN, _DELETED, _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, 4331f6eb021SLiane Praza * _NO_RESOURCES, _NOT_BOUND, _PERMISSION_DENIED, or _TEMPLATE_INVALID. 4341f6eb021SLiane Praza */ 4351f6eb021SLiane Praza char * 4361f6eb021SLiane Praza _scf_read_tmpl_prop_type_as_string(const scf_prop_tmpl_t *pt) 4371f6eb021SLiane Praza { 4381f6eb021SLiane Praza char *type; 4391f6eb021SLiane Praza 4401f6eb021SLiane Praza type = _scf_read_single_astring_from_pg(pt->prt_pg, 4411f6eb021SLiane Praza SCF_PROPERTY_TM_TYPE); 4421f6eb021SLiane Praza if (type == NULL) { 4431f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 4441f6eb021SLiane Praza return (NULL); 4451f6eb021SLiane Praza } else switch (scf_error()) { 4461f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 4471f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 4481f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 4491f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 4501f6eb021SLiane Praza return (NULL); 4511f6eb021SLiane Praza 4521f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 4531f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 4541f6eb021SLiane Praza default: 4551f6eb021SLiane Praza assert(0); 4561f6eb021SLiane Praza abort(); 4571f6eb021SLiane Praza } 4581f6eb021SLiane Praza } 4591f6eb021SLiane Praza 4601f6eb021SLiane Praza return (type); 4611f6eb021SLiane Praza } 4621f6eb021SLiane Praza 4631f6eb021SLiane Praza /* 4641f6eb021SLiane Praza * int _read_single_boolean_from_pg() 4651f6eb021SLiane Praza * 4661f6eb021SLiane Praza * Reads a boolean from the pg and property name specified. 4671f6eb021SLiane Praza * 4681f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 4691f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 4701f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 4711f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 4721f6eb021SLiane Praza * Property has more than one value associated with it. 4731f6eb021SLiane Praza * SCF_ERROR_DELETED 4741f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 4751f6eb021SLiane Praza * SCF_ERROR_INTERNAL 4761f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 4771f6eb021SLiane Praza * prop_name is not a valid property name. 4781f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4791f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 4801f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 4811f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 4821f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 4831f6eb021SLiane Praza * SCF_ERROR_NOT_SET 4841f6eb021SLiane Praza * The property group specified by pg is not set. 4851f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 4861f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 4871f6eb021SLiane Praza */ 4881f6eb021SLiane Praza static int 4891f6eb021SLiane Praza _read_single_boolean_from_pg(scf_propertygroup_t *pg, const char *prop_name, 4901f6eb021SLiane Praza uint8_t *bool) 4911f6eb021SLiane Praza { 4921f6eb021SLiane Praza scf_value_t *val; 4931f6eb021SLiane Praza int ret = 0; 4941f6eb021SLiane Praza 4951f6eb021SLiane Praza if (_read_single_value_from_pg(pg, prop_name, &val) == -1) 4961f6eb021SLiane Praza return (-1); 4971f6eb021SLiane Praza 4981f6eb021SLiane Praza if (scf_value_get_boolean(val, bool) < 0) { 4991f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 5001f6eb021SLiane Praza ret = -1; 5011f6eb021SLiane Praza } 5021f6eb021SLiane Praza 5031f6eb021SLiane Praza scf_value_destroy(val); 5041f6eb021SLiane Praza return (ret); 5051f6eb021SLiane Praza } 5061f6eb021SLiane Praza 5071f6eb021SLiane Praza /* 508f6e214c7SGavin Maltby * static char ** _append_astrings_values() 5091f6eb021SLiane Praza * 5101f6eb021SLiane Praza * This function reads the values from the property prop_name in pg and 5111f6eb021SLiane Praza * appends to an existing scf_values_t *vals. vals may be empty, but 5121f6eb021SLiane Praza * must exist. The function skips over zero-length and duplicate values. 5131f6eb021SLiane Praza * 5141f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 5151f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5161f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5171f6eb021SLiane Praza * SCF_ERROR_DELETED 5181f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5191f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5201f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 5211f6eb021SLiane Praza * prop_name is not a valid property name. 5221f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5231f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5241f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5251f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 5261f6eb021SLiane Praza * SCF_ERROR_NOT_SET 5271f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5281f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 5291f6eb021SLiane Praza */ 5301f6eb021SLiane Praza static char ** 5311f6eb021SLiane Praza _append_astrings_values(scf_propertygroup_t *pg, const char *prop_name, 5321f6eb021SLiane Praza scf_values_t *vals) 5331f6eb021SLiane Praza { 5341f6eb021SLiane Praza scf_handle_t *h; 5351f6eb021SLiane Praza scf_property_t *prop; 5361f6eb021SLiane Praza scf_value_t *val; 5371f6eb021SLiane Praza scf_iter_t *iter; 5381f6eb021SLiane Praza ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 5391f6eb021SLiane Praza int err, count, cursz, i; 5401f6eb021SLiane Praza 5411f6eb021SLiane Praza assert(vals != NULL); 5421f6eb021SLiane Praza assert(vals->value_type == SCF_TYPE_ASTRING); 5431f6eb021SLiane Praza assert(vals->reserved == NULL); 5441f6eb021SLiane Praza count = vals->value_count; 5451f6eb021SLiane Praza if (count == 0) { 5461f6eb021SLiane Praza cursz = 8; 5471f6eb021SLiane Praza vals->values.v_astring = calloc(cursz, sizeof (char *)); 5481f6eb021SLiane Praza if (vals->values.v_astring == NULL) { 5491f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5501f6eb021SLiane Praza return (NULL); 5511f6eb021SLiane Praza } 5521f6eb021SLiane Praza } else { 5531f6eb021SLiane Praza /* 5541f6eb021SLiane Praza * The array may be bigger, but it is irrelevant since 5551f6eb021SLiane Praza * we will always re-allocate a new one. 5561f6eb021SLiane Praza */ 5571f6eb021SLiane Praza cursz = count; 5581f6eb021SLiane Praza } 5591f6eb021SLiane Praza 5601f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) { 5611f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 5621f6eb021SLiane Praza return (NULL); 5631f6eb021SLiane Praza } 5641f6eb021SLiane Praza 5651f6eb021SLiane Praza prop = scf_property_create(h); 5661f6eb021SLiane Praza val = scf_value_create(h); 5671f6eb021SLiane Praza iter = scf_iter_create(h); 5681f6eb021SLiane Praza 5691f6eb021SLiane Praza if (prop == NULL || val == NULL || iter == NULL) { 5701f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 5711f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 5721f6eb021SLiane Praza } 5731f6eb021SLiane Praza 5741f6eb021SLiane Praza if (scf_pg_get_property(pg, prop_name, prop) != 0) { 5751f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 5761f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 5771f6eb021SLiane Praza } 5781f6eb021SLiane Praza 5791f6eb021SLiane Praza if (scf_iter_property_values(iter, prop) != 0) { 5801f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 5811f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 5821f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 5831f6eb021SLiane Praza } 5841f6eb021SLiane Praza 5851f6eb021SLiane Praza while ((err = scf_iter_next_value(iter, val)) == 1) { 5861f6eb021SLiane Praza int flag; 5871f6eb021SLiane Praza int r; 5881f6eb021SLiane Praza 5891f6eb021SLiane Praza if (count + 1 >= cursz) { 5901f6eb021SLiane Praza void *aux; 5911f6eb021SLiane Praza 5921f6eb021SLiane Praza cursz *= 2; 5931f6eb021SLiane Praza if ((aux = calloc(cursz, sizeof (char *))) == NULL) { 5941f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5951f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 5961f6eb021SLiane Praza } 5971f6eb021SLiane Praza (void) memcpy(aux, vals->values.v_astring, 5981f6eb021SLiane Praza count * sizeof (char *)); 5991f6eb021SLiane Praza free(vals->values.v_astring); 6001f6eb021SLiane Praza vals->values.v_astring = aux; 6011f6eb021SLiane Praza } 6021f6eb021SLiane Praza 6031f6eb021SLiane Praza vals->values.v_astring[count] = malloc(rsize); 6041f6eb021SLiane Praza if (vals->values.v_astring[count] == NULL) { 6051f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 6061f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 6071f6eb021SLiane Praza } 6081f6eb021SLiane Praza 6091f6eb021SLiane Praza if ((r = scf_value_get_astring(val, 6101f6eb021SLiane Praza vals->values.v_astring[count], rsize)) <= 0) { 6111f6eb021SLiane Praza /* discard zero length strings */ 6121f6eb021SLiane Praza if (r == 0) { 6131f6eb021SLiane Praza free(vals->values.v_astring[count]); 6141f6eb021SLiane Praza continue; 6151f6eb021SLiane Praza } 6161f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 6171f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 6181f6eb021SLiane Praza } 6191f6eb021SLiane Praza for (i = 0, flag = 0; i < count; ++i) { 6201f6eb021SLiane Praza /* find and discard duplicates */ 6211f6eb021SLiane Praza if (strncmp(vals->values.v_astring[i], 6221f6eb021SLiane Praza vals->values.v_astring[count], rsize) == 0) { 6231f6eb021SLiane Praza free(vals->values.v_astring[count]); 6241f6eb021SLiane Praza flag = 1; 6251f6eb021SLiane Praza break; 6261f6eb021SLiane Praza } 6271f6eb021SLiane Praza } 6281f6eb021SLiane Praza if (flag == 1) 6291f6eb021SLiane Praza continue; 6301f6eb021SLiane Praza 6311f6eb021SLiane Praza count++; 6321f6eb021SLiane Praza } 6331f6eb021SLiane Praza 6341f6eb021SLiane Praza vals->value_count = count; 6351f6eb021SLiane Praza 6361f6eb021SLiane Praza if (err != 0) { 6371f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 6381f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 6391f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 6401f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 6411f6eb021SLiane Praza } else { 6421f6eb021SLiane Praza vals->values_as_strings = vals->values.v_astring; 6431f6eb021SLiane Praza } 6441f6eb021SLiane Praza 6451f6eb021SLiane Praza goto append_single_astring_from_pg_done; 6461f6eb021SLiane Praza 6471f6eb021SLiane Praza append_single_astring_from_pg_fail: 6481f6eb021SLiane Praza for (i = 0; i <= count; ++i) { 6491f6eb021SLiane Praza if (vals->values.v_astring[i] != NULL) 6501f6eb021SLiane Praza free(vals->values.v_astring[i]); 6511f6eb021SLiane Praza vals->values.v_astring[i] = NULL; 6521f6eb021SLiane Praza } 6531f6eb021SLiane Praza free(vals->values.v_astring); 6541f6eb021SLiane Praza vals->values.v_astring = NULL; 6551f6eb021SLiane Praza vals->value_count = 0; 6561f6eb021SLiane Praza 6571f6eb021SLiane Praza append_single_astring_from_pg_done: 6581f6eb021SLiane Praza scf_iter_destroy(iter); 6591f6eb021SLiane Praza scf_property_destroy(prop); 6601f6eb021SLiane Praza scf_value_destroy(val); 6611f6eb021SLiane Praza return (vals->values.v_astring); 6621f6eb021SLiane Praza } 6631f6eb021SLiane Praza 6641f6eb021SLiane Praza /* 6651f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 6661f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 6671f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 6681f6eb021SLiane Praza * SCF_ERROR_DELETED 6691f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 6701f6eb021SLiane Praza * SCF_ERROR_INTERNAL 6711f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 6721f6eb021SLiane Praza * prop_name is not a valid property name. 6731f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 6741f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 6751f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 6761f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 6771f6eb021SLiane Praza * SCF_ERROR_NOT_SET 6781f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 6791f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 6801f6eb021SLiane Praza */ 6811f6eb021SLiane Praza static char ** 6821f6eb021SLiane Praza _read_astrings_values(scf_propertygroup_t *pg, const char *prop_name, 6831f6eb021SLiane Praza scf_values_t *vals) 6841f6eb021SLiane Praza { 6851f6eb021SLiane Praza assert(vals != NULL); 6861f6eb021SLiane Praza vals->value_count = 0; 6871f6eb021SLiane Praza vals->value_type = SCF_TYPE_ASTRING; 6881f6eb021SLiane Praza vals->reserved = NULL; 6891f6eb021SLiane Praza return (_append_astrings_values(pg, prop_name, vals)); 6901f6eb021SLiane Praza } 6911f6eb021SLiane Praza 6921f6eb021SLiane Praza void 6931f6eb021SLiane Praza _scf_sanitize_locale(char *locale) 6941f6eb021SLiane Praza { 6951f6eb021SLiane Praza for (; *locale != '\0'; locale++) 6961f6eb021SLiane Praza if (!isalnum(*locale) && *locale != '_') 6971f6eb021SLiane Praza *locale = '_'; 6981f6eb021SLiane Praza } 6991f6eb021SLiane Praza 7001f6eb021SLiane Praza /* 7011f6eb021SLiane Praza * The returned string needs to be freed by the caller 7021f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error() to: 7031f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 7041f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 7051f6eb021SLiane Praza * Name isn't short enough to add the locale to. 7061f6eb021SLiane Praza */ 7071f6eb021SLiane Praza static char * 7081f6eb021SLiane Praza _add_locale_to_name(const char *name, const char *locale) 7091f6eb021SLiane Praza { 7101f6eb021SLiane Praza char *lname = NULL; 7111f6eb021SLiane Praza ssize_t lsz; 7121f6eb021SLiane Praza char *loc; 7131f6eb021SLiane Praza 7141f6eb021SLiane Praza if (locale == NULL) 7151f6eb021SLiane Praza locale = setlocale(LC_MESSAGES, NULL); 7161f6eb021SLiane Praza loc = strdup(locale); 7171f6eb021SLiane Praza if (loc == NULL) { 7181f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 7191f6eb021SLiane Praza return (NULL); 7201f6eb021SLiane Praza } else { 7211f6eb021SLiane Praza _scf_sanitize_locale(loc); 7221f6eb021SLiane Praza } 7231f6eb021SLiane Praza 7241f6eb021SLiane Praza lsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 7251f6eb021SLiane Praza lname = malloc(lsz); 7261f6eb021SLiane Praza if (lname == NULL) { 7271f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 7281f6eb021SLiane Praza goto cleanup; 7291f6eb021SLiane Praza } 7301f6eb021SLiane Praza 7311f6eb021SLiane Praza (void) strlcpy(lname, name, lsz); 7321f6eb021SLiane Praza if (strlcat(lname, loc, lsz) >= lsz) { 7331f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 7341f6eb021SLiane Praza free(lname); 7351f6eb021SLiane Praza lname = NULL; 7361f6eb021SLiane Praza } 7371f6eb021SLiane Praza cleanup: 7381f6eb021SLiane Praza free(loc); 7391f6eb021SLiane Praza 7401f6eb021SLiane Praza return (lname); 7411f6eb021SLiane Praza } 7421f6eb021SLiane Praza 7431f6eb021SLiane Praza /* 7441f6eb021SLiane Praza * char *_tmpl_pg_name(pg, type, use_type) 7451f6eb021SLiane Praza * 7461f6eb021SLiane Praza * pg and type can both be NULL. Returns the name of the most specific 7471f6eb021SLiane Praza * template property group name based on the inputs. 7481f6eb021SLiane Praza * If use_type is set and pg is not NULL, a property group name for a 7491f6eb021SLiane Praza * property group template that has type defined is returned, even if no 7501f6eb021SLiane Praza * type is provided. 7511f6eb021SLiane Praza * 7521f6eb021SLiane Praza * Returns NULL on failure and sets scf_error() to: 7531f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 7541f6eb021SLiane Praza * can't combine the arguments and get a reasonable length name 7551f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 7561f6eb021SLiane Praza * 7571f6eb021SLiane Praza */ 7581f6eb021SLiane Praza static char * 7591f6eb021SLiane Praza _tmpl_pg_name(const char *pg, const char *type, int use_type) 7601f6eb021SLiane Praza { 7611f6eb021SLiane Praza char *name; 7621f6eb021SLiane Praza ssize_t limit, size = 0; 7631f6eb021SLiane Praza 7641f6eb021SLiane Praza limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 7651f6eb021SLiane Praza name = malloc(limit); 7661f6eb021SLiane Praza if (name == NULL) { 7671f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 7681f6eb021SLiane Praza return (NULL); 7691f6eb021SLiane Praza } 7701f6eb021SLiane Praza 7711f6eb021SLiane Praza if (pg == NULL && type == NULL) { 7721f6eb021SLiane Praza if (strlcpy(name, SCF_PG_TM_PG_PATTERN_PREFIX, limit) >= 7731f6eb021SLiane Praza limit) { 7741f6eb021SLiane Praza assert(0); 7751f6eb021SLiane Praza abort(); 7761f6eb021SLiane Praza } 7771f6eb021SLiane Praza return (name); 7781f6eb021SLiane Praza } else if (pg != NULL && type != NULL) { 7791f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 7801f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg); 7811f6eb021SLiane Praza } else if (pg != NULL && type == NULL && use_type == 1) { 7821f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 7831f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg); 7841f6eb021SLiane Praza } else if (pg != NULL && type == NULL) { 7851f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 7861f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_N_PREFIX, pg); 7871f6eb021SLiane Praza } else if (type != NULL && pg == NULL) { 7881f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 7891f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_T_PREFIX, type); 7901f6eb021SLiane Praza } else { 7911f6eb021SLiane Praza assert(0); 7921f6eb021SLiane Praza abort(); 7931f6eb021SLiane Praza } 7941f6eb021SLiane Praza 7951f6eb021SLiane Praza if (size >= limit) { 7961f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 7971f6eb021SLiane Praza free(name); 7981f6eb021SLiane Praza return (NULL); 7991f6eb021SLiane Praza } else { 8001f6eb021SLiane Praza return (name); 8011f6eb021SLiane Praza } 8021f6eb021SLiane Praza } 8031f6eb021SLiane Praza 8041f6eb021SLiane Praza /* 8051f6eb021SLiane Praza * _scf_get_pg_name() 8061f6eb021SLiane Praza * Gets the name of the supplied property group. On success, returns an 8071f6eb021SLiane Praza * allocated string. The string must be freed by free(). 8081f6eb021SLiane Praza * 8091f6eb021SLiane Praza * Returns NULL on failure and sets scf_error() to _CONNECTION_BROKEN, 8101f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 8111f6eb021SLiane Praza */ 8121f6eb021SLiane Praza static char * 8131f6eb021SLiane Praza _scf_get_pg_name(scf_propertygroup_t *pg) 8141f6eb021SLiane Praza { 8151f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 8161f6eb021SLiane Praza char *buf = malloc(sz); 8171f6eb021SLiane Praza 8181f6eb021SLiane Praza if (buf == NULL) { 8191f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 8201f6eb021SLiane Praza } else if (scf_pg_get_name(pg, buf, sz) == -1) { 8211f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 8221f6eb021SLiane Praza free(buf); 8231f6eb021SLiane Praza buf = NULL; 8241f6eb021SLiane Praza } else { 8251f6eb021SLiane Praza assert(0); 8261f6eb021SLiane Praza abort(); 8271f6eb021SLiane Praza } 8281f6eb021SLiane Praza } 8291f6eb021SLiane Praza 8301f6eb021SLiane Praza return (buf); 8311f6eb021SLiane Praza } 8321f6eb021SLiane Praza 8331f6eb021SLiane Praza /* 8341f6eb021SLiane Praza * char *_tmpl_prop_name() 8351f6eb021SLiane Praza * 8361f6eb021SLiane Praza * Returns the name of the property template prop (which is the name of 8371f6eb021SLiane Praza * the property template property group) in the property group 8381f6eb021SLiane Praza * template t. Returns NULL on failure and sets scf_error() to: 8391f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 8401f6eb021SLiane Praza * SCF_ERROR_DELETED 8411f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 8421f6eb021SLiane Praza * can't combine the arguments and get a reasonable length name 8431f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 8441f6eb021SLiane Praza */ 8451f6eb021SLiane Praza static char * 8461f6eb021SLiane Praza _tmpl_prop_name(const char *prop, scf_pg_tmpl_t *t) 8471f6eb021SLiane Praza { 8481f6eb021SLiane Praza char *name = NULL, *pg_name = NULL; 8491f6eb021SLiane Praza size_t prefix_size; 8501f6eb021SLiane Praza ssize_t limit, size = 0; 8511f6eb021SLiane Praza 8521f6eb021SLiane Praza assert(prop != NULL); 8531f6eb021SLiane Praza assert(t->pt_pg != NULL); 8541f6eb021SLiane Praza 8551f6eb021SLiane Praza limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 8561f6eb021SLiane Praza name = malloc(limit); 8571f6eb021SLiane Praza if (name == NULL) { 8581f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 8591f6eb021SLiane Praza return (NULL); 8601f6eb021SLiane Praza } 8611f6eb021SLiane Praza 8621f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(t->pt_pg)) == NULL) { 8631f6eb021SLiane Praza free(name); 8641f6eb021SLiane Praza return (NULL); 8651f6eb021SLiane Praza } 8661f6eb021SLiane Praza 8671f6eb021SLiane Praza prefix_size = strlen(SCF_PG_TM_PG_PAT_BASE); 8681f6eb021SLiane Praza if (strncmp(pg_name, SCF_PG_TM_PG_PAT_BASE, prefix_size) != 0) { 8691f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 8701f6eb021SLiane Praza free(name); 8711f6eb021SLiane Praza free(pg_name); 8721f6eb021SLiane Praza return (NULL); 8731f6eb021SLiane Praza } 8741f6eb021SLiane Praza 8751f6eb021SLiane Praza size = snprintf(name, limit, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX, 8761f6eb021SLiane Praza pg_name + prefix_size, prop); 8771f6eb021SLiane Praza 8781f6eb021SLiane Praza if (size >= limit) { 8791f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 8801f6eb021SLiane Praza free(name); 8811f6eb021SLiane Praza free(pg_name); 8821f6eb021SLiane Praza return (NULL); 8831f6eb021SLiane Praza } else { 8841f6eb021SLiane Praza free(pg_name); 8851f6eb021SLiane Praza return (name); 8861f6eb021SLiane Praza } 8871f6eb021SLiane Praza } 8881f6eb021SLiane Praza 8891f6eb021SLiane Praza /* 8901f6eb021SLiane Praza * int _get_snapshot() 8911f6eb021SLiane Praza * 8921f6eb021SLiane Praza * Gets the specified snapshot. If "snapshot" isn't defined, use the 8931f6eb021SLiane Praza * running snapshot. If the snapshot isn't found, that may or may 8941f6eb021SLiane Praza * not be an error depending on the caller. Return 0 in that case, 8951f6eb021SLiane Praza * but leave scf_error() set to SCF_ERROR_NOT_FOUND. On all other 8961f6eb021SLiane Praza * errors, set scf_error() to: 8971f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 8981f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 8991f6eb021SLiane Praza * SCF_ERROR_DELETED 9001f6eb021SLiane Praza * SCF_ERR_HANDLE_DESTROYED 9011f6eb021SLiane Praza * SCF_ERROR_INTERNAL 9021f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 9031f6eb021SLiane Praza * The handle argument is NULL, or snaphot is not a valid snapshot name 9041f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 9051f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 9061f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 9071f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 9081f6eb021SLiane Praza */ 9091f6eb021SLiane Praza static int 9101f6eb021SLiane Praza _get_snapshot(scf_instance_t *inst, const char *snapshot, 9111f6eb021SLiane Praza scf_snapshot_t **snap) 9121f6eb021SLiane Praza { 9131f6eb021SLiane Praza int err; 9141f6eb021SLiane Praza scf_handle_t *h; 9151f6eb021SLiane Praza 9161f6eb021SLiane Praza h = scf_instance_handle(inst); 917*a58a7fedSMilan Jurik if (h == NULL) { 918*a58a7fedSMilan Jurik *snap = NULL; 9191f6eb021SLiane Praza return (-1); 920*a58a7fedSMilan Jurik } 9211f6eb021SLiane Praza 9221f6eb021SLiane Praza if ((*snap = scf_snapshot_create(h)) == NULL) { 9231f6eb021SLiane Praza return (-1); 9241f6eb021SLiane Praza } 9251f6eb021SLiane Praza 9261f6eb021SLiane Praza /* Use running snapshot by default. */ 9271f6eb021SLiane Praza if (snapshot == NULL) 9281f6eb021SLiane Praza err = scf_instance_get_snapshot(inst, "running", *snap); 9291f6eb021SLiane Praza else 9301f6eb021SLiane Praza err = scf_instance_get_snapshot(inst, snapshot, *snap); 9311f6eb021SLiane Praza 9321f6eb021SLiane Praza if (err != 0) { 9331f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 9341f6eb021SLiane Praza scf_snapshot_destroy(*snap); 9351f6eb021SLiane Praza *snap = NULL; 9361f6eb021SLiane Praza return (-1); 9371f6eb021SLiane Praza } else switch (scf_error()) { 9381f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 9391f6eb021SLiane Praza scf_snapshot_destroy(*snap); 9401f6eb021SLiane Praza *snap = NULL; 9411f6eb021SLiane Praza return (-1); 9421f6eb021SLiane Praza 9431f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 9441f6eb021SLiane Praza scf_snapshot_destroy(*snap); 9451f6eb021SLiane Praza *snap = NULL; 9461f6eb021SLiane Praza return (0); 9471f6eb021SLiane Praza 9481f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 9491f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 9501f6eb021SLiane Praza default: 9511f6eb021SLiane Praza assert(0); 9521f6eb021SLiane Praza abort(); 9531f6eb021SLiane Praza } 9541f6eb021SLiane Praza } 9551f6eb021SLiane Praza 9561f6eb021SLiane Praza /* 9571f6eb021SLiane Praza * Explicitly set SCF_ERROR_NONE so that the SCF_ERROR_NOT_FOUND 9581f6eb021SLiane Praza * return above is explicitly guaranteed to be from 9591f6eb021SLiane Praza * scf_instance_get_snapshot(). 9601f6eb021SLiane Praza */ 9611f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 9621f6eb021SLiane Praza return (0); 9631f6eb021SLiane Praza } 9641f6eb021SLiane Praza 9651f6eb021SLiane Praza /* 9661f6eb021SLiane Praza * Returns NULL on error, sets scf_error() to: 9671f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 9681f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 9691f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 9701f6eb021SLiane Praza * The restarter's FMRI does not match an existing instance. 9711f6eb021SLiane Praza * SCF_ERROR_DELETED 9721f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 9731f6eb021SLiane Praza * SCF_ERROR_INTERNAL 9741f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 9751f6eb021SLiane Praza * The restarter's FMRI is not a valid FMRI. 9761f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 9771f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 9781f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 9791f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 9801f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 9811f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 9821f6eb021SLiane Praza * restarter property is not SCF_TYPE_ASTRING or has more than one value 9831f6eb021SLiane Praza */ 9841f6eb021SLiane Praza static scf_instance_t * 9851f6eb021SLiane Praza _get_restarter_inst(scf_handle_t *h, scf_service_t *svc, 9861f6eb021SLiane Praza scf_instance_t *inst, scf_snapshot_t *s) 9871f6eb021SLiane Praza { 9881f6eb021SLiane Praza char *restarter = NULL; 9891f6eb021SLiane Praza scf_instance_t *ri = NULL; 9901f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 9911f6eb021SLiane Praza int ret = 0; 9921f6eb021SLiane Praza 9931f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 9941f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 9951f6eb021SLiane Praza 9961f6eb021SLiane Praza if ((ri = scf_instance_create(h)) == NULL || 9971f6eb021SLiane Praza (pg = scf_pg_create(h)) == NULL) { 9981f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 99976fa7285SAntonello Cruz goto _get_restarter_inst_fail; 10001f6eb021SLiane Praza } 10011f6eb021SLiane Praza 10021f6eb021SLiane Praza if (inst != NULL) 10031f6eb021SLiane Praza ret = scf_instance_get_pg_composed(inst, s, SCF_PG_GENERAL, 10041f6eb021SLiane Praza pg); 10051f6eb021SLiane Praza else 10061f6eb021SLiane Praza ret = scf_service_get_pg(svc, SCF_PG_GENERAL, pg); 10071f6eb021SLiane Praza 10081f6eb021SLiane Praza if (ret != 0) { 10091f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 10101f6eb021SLiane Praza goto _get_restarter_inst_fail; 10111f6eb021SLiane Praza } else switch (scf_error()) { 10121f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 10131f6eb021SLiane Praza /* Assume default restarter. */ 10141f6eb021SLiane Praza break; 10151f6eb021SLiane Praza 10161f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 10171f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 10181f6eb021SLiane Praza /* 10191f6eb021SLiane Praza * If the arguments to the above functions 10201f6eb021SLiane Praza * aren't derived from the same handle, there's 10211f6eb021SLiane Praza * something wrong with the internal implementation, 10221f6eb021SLiane Praza * not the public caller further up the chain. 10231f6eb021SLiane Praza */ 10241f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 10251f6eb021SLiane Praza default: 10261f6eb021SLiane Praza assert(0); 10271f6eb021SLiane Praza abort(); 10281f6eb021SLiane Praza } 10291f6eb021SLiane Praza } else { 10301f6eb021SLiane Praza restarter = _scf_read_single_astring_from_pg(pg, 10311f6eb021SLiane Praza SCF_PROPERTY_RESTARTER); 10321f6eb021SLiane Praza /* zero length string is NOT a valid restarter */ 10331f6eb021SLiane Praza if (restarter != NULL && restarter[0] == '\0') { 10341f6eb021SLiane Praza free(restarter); 10351f6eb021SLiane Praza restarter = NULL; 10361f6eb021SLiane Praza } else if (restarter == NULL) { 10371f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 10381f6eb021SLiane Praza goto _get_restarter_inst_fail; 10391f6eb021SLiane Praza } else switch (scf_error()) { 10401f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 10411f6eb021SLiane Praza break; 10421f6eb021SLiane Praza 10431f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 10441f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 10451f6eb021SLiane Praza (void) scf_set_error( 10461f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 10471f6eb021SLiane Praza goto _get_restarter_inst_fail; 10481f6eb021SLiane Praza 10491f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 10501f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 10511f6eb021SLiane Praza default: 10521f6eb021SLiane Praza assert(0); 10531f6eb021SLiane Praza abort(); 10541f6eb021SLiane Praza } 10551f6eb021SLiane Praza } 10561f6eb021SLiane Praza } 10571f6eb021SLiane Praza 10581f6eb021SLiane Praza if (restarter == NULL) { 10591f6eb021SLiane Praza /* Use default restarter */ 10601f6eb021SLiane Praza restarter = strdup(SCF_SERVICE_STARTD); 10611f6eb021SLiane Praza if (restarter == NULL) { 10621f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 10631f6eb021SLiane Praza goto _get_restarter_inst_fail; 10641f6eb021SLiane Praza } 10651f6eb021SLiane Praza } 10661f6eb021SLiane Praza 10671f6eb021SLiane Praza if (scf_handle_decode_fmri(h, restarter, NULL, NULL, ri, NULL, NULL, 10681f6eb021SLiane Praza SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 10691f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 10701f6eb021SLiane Praza goto _get_restarter_inst_fail; 10711f6eb021SLiane Praza } else switch (scf_error()) { 10721f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 10731f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 10741f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 10751f6eb021SLiane Praza goto _get_restarter_inst_fail; 10761f6eb021SLiane Praza 10771f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 10781f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 10791f6eb021SLiane Praza default: 10801f6eb021SLiane Praza assert(0); 10811f6eb021SLiane Praza abort(); 10821f6eb021SLiane Praza } 10831f6eb021SLiane Praza } 10841f6eb021SLiane Praza free(restarter); 10851f6eb021SLiane Praza scf_pg_destroy(pg); 10861f6eb021SLiane Praza 10871f6eb021SLiane Praza return (ri); 10881f6eb021SLiane Praza 10891f6eb021SLiane Praza _get_restarter_inst_fail: 109076fa7285SAntonello Cruz free(restarter); 10911f6eb021SLiane Praza scf_instance_destroy(ri); 10921f6eb021SLiane Praza scf_pg_destroy(pg); 10931f6eb021SLiane Praza return (NULL); 10941f6eb021SLiane Praza } 10951f6eb021SLiane Praza 10961f6eb021SLiane Praza /* 10971f6eb021SLiane Praza * Returns NULL on error, sets scf_error() to: 10981f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 10991f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 11001f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 11011f6eb021SLiane Praza * Restarter property has more than one value associated with it, 11021f6eb021SLiane Praza * or FMRI does not meet restrictions in scf_handle_decode_fmri() flags. 11031f6eb021SLiane Praza * SCF_ERROR_DELETED 11041f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 11051f6eb021SLiane Praza * SCF_ERROR_INTERNAL 11061f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 11071f6eb021SLiane Praza * The fmri argument in scf_handle_decode_fmri() is not a valid FMRI. 11081f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 11091f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 11101f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 11111f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 11121f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 11131f6eb021SLiane Praza */ 11141f6eb021SLiane Praza static scf_instance_t * 11151f6eb021SLiane Praza _get_global_inst(scf_handle_t *h) 11161f6eb021SLiane Praza { 11171f6eb021SLiane Praza scf_instance_t *ri; 11181f6eb021SLiane Praza 11191f6eb021SLiane Praza if ((ri = scf_instance_create(h)) == NULL) { 11201f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 11211f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_RESOURCES); 11221f6eb021SLiane Praza return (NULL); 11231f6eb021SLiane Praza } 11241f6eb021SLiane Praza 11251f6eb021SLiane Praza if (scf_handle_decode_fmri(h, SCF_INSTANCE_GLOBAL, NULL, NULL, ri, 11261f6eb021SLiane Praza NULL, NULL, 11271f6eb021SLiane Praza SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 11281f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 11291f6eb021SLiane Praza scf_instance_destroy(ri); 11301f6eb021SLiane Praza return (NULL); 11311f6eb021SLiane Praza } else switch (scf_error()) { 11321f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 11331f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 11341f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 11351f6eb021SLiane Praza scf_instance_destroy(ri); 11361f6eb021SLiane Praza return (NULL); 11371f6eb021SLiane Praza 11381f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 11391f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 11401f6eb021SLiane Praza default: 11411f6eb021SLiane Praza assert(0); 11421f6eb021SLiane Praza abort(); 11431f6eb021SLiane Praza } 11441f6eb021SLiane Praza } 11451f6eb021SLiane Praza 11461f6eb021SLiane Praza return (ri); 11471f6eb021SLiane Praza } 11481f6eb021SLiane Praza 11491f6eb021SLiane Praza /* 11501f6eb021SLiane Praza * Call the supplied function for each of the service or instance, the 11511f6eb021SLiane Praza * service's restarter, and the globally defined template instance. 11521f6eb021SLiane Praza * If the function returns SCF_WALK_ERROR, the walk is ended. If 11531f6eb021SLiane Praza * the function returns SCF_WALK_NEXT, the next entity is tried. 11541f6eb021SLiane Praza * 11551f6eb021SLiane Praza * The function is only expected to return SCF_WALK_DONE if it has 11561f6eb021SLiane Praza * found a property group match in the current entity, and has 11571f6eb021SLiane Praza * populated p->pw_pg with the matching property group. 115876fa7285SAntonello Cruz * 115976fa7285SAntonello Cruz * The caller of _walk_template_instances() MUST check if the passed parameters 116076fa7285SAntonello Cruz * inst and svc match the fields pw_inst and pw_svc in the resulting 116176fa7285SAntonello Cruz * pg_tmpl_walk_t and call the destructor for the unmatching objects. The walker 116276fa7285SAntonello Cruz * may silently drop them if the template definition is in the restarter or in 116376fa7285SAntonello Cruz * the global instance. 11641f6eb021SLiane Praza */ 11651f6eb021SLiane Praza static void 11661f6eb021SLiane Praza _walk_template_instances(scf_service_t *svc, scf_instance_t *inst, 11671f6eb021SLiane Praza scf_snapshot_t *snap, walk_template_inst_func_t *func, 11681f6eb021SLiane Praza pg_tmpl_walk_t *p, int flag) 11691f6eb021SLiane Praza { 11701f6eb021SLiane Praza scf_instance_t *tmpl_inst = NULL; 11711f6eb021SLiane Praza scf_handle_t *h; 11721f6eb021SLiane Praza int ret; 11731f6eb021SLiane Praza char *tg = NULL; 11741f6eb021SLiane Praza 11751f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 11761f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 11771f6eb021SLiane Praza 11781f6eb021SLiane Praza if (inst != NULL) 11791f6eb021SLiane Praza h = scf_instance_handle(inst); 11801f6eb021SLiane Praza else 11811f6eb021SLiane Praza h = scf_service_handle(svc); 11821f6eb021SLiane Praza if (h == NULL) 11831f6eb021SLiane Praza goto done; 11841f6eb021SLiane Praza 11851f6eb021SLiane Praza /* First, use supplied service or instance */ 11861f6eb021SLiane Praza p->pw_target = SCF_TM_TARGET_THIS; 11871f6eb021SLiane Praza ret = func(svc, inst, p); 11881f6eb021SLiane Praza switch (ret) { 11891f6eb021SLiane Praza case SCF_WALK_NEXT: 11901f6eb021SLiane Praza break; 11911f6eb021SLiane Praza case SCF_WALK_DONE: 11921f6eb021SLiane Praza /* 11931f6eb021SLiane Praza * Check that the template scoping matches and if not, 11941f6eb021SLiane Praza * continue. 11951f6eb021SLiane Praza */ 11961f6eb021SLiane Praza assert(p->pw_pg != NULL); 11971f6eb021SLiane Praza tg = _scf_read_single_astring_from_pg(p->pw_pg, 11981f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 11991f6eb021SLiane Praza if (tg == NULL || /* scf_error() was set */ 12001f6eb021SLiane Praza (strcmp(tg, SCF_TM_TARGET_INSTANCE) != 0 && 12011f6eb021SLiane Praza strcmp(tg, SCF_TM_TARGET_THIS) != 0 && 12021f6eb021SLiane Praza (flag & SCF_PG_TMPL_FLAG_EXACT) != 12031f6eb021SLiane Praza SCF_PG_TMPL_FLAG_EXACT)) { 12041f6eb021SLiane Praza scf_pg_destroy(p->pw_pg); 12051f6eb021SLiane Praza p->pw_pg = NULL; 12061f6eb021SLiane Praza if (tg != NULL) { 12071f6eb021SLiane Praza free(tg); 12081f6eb021SLiane Praza tg = NULL; 12091f6eb021SLiane Praza break; 12101f6eb021SLiane Praza } 12111f6eb021SLiane Praza } 12121f6eb021SLiane Praza /*FALLTHROUGH*/ 12131f6eb021SLiane Praza case SCF_WALK_ERROR: 12141f6eb021SLiane Praza goto done; 12151f6eb021SLiane Praza /*NOTREACHED*/ 12161f6eb021SLiane Praza default: 12171f6eb021SLiane Praza assert(0); 12181f6eb021SLiane Praza abort(); 12191f6eb021SLiane Praza } 12201f6eb021SLiane Praza 12211f6eb021SLiane Praza /* Next the restarter. */ 12221f6eb021SLiane Praza p->pw_target = SCF_TM_TARGET_DELEGATE; 12231f6eb021SLiane Praza tmpl_inst = _get_restarter_inst(h, svc, inst, snap); 12241f6eb021SLiane Praza if (tmpl_inst != NULL) { 12251f6eb021SLiane Praza ret = func(NULL, tmpl_inst, p); 12261f6eb021SLiane Praza switch (ret) { 12271f6eb021SLiane Praza case SCF_WALK_NEXT: 12281f6eb021SLiane Praza break; 12291f6eb021SLiane Praza case SCF_WALK_DONE: 12301f6eb021SLiane Praza /* 12311f6eb021SLiane Praza * Check that the template scoping matches and if not, 12321f6eb021SLiane Praza * continue. 12331f6eb021SLiane Praza */ 12341f6eb021SLiane Praza assert(p->pw_pg != NULL); 12351f6eb021SLiane Praza tg = _scf_read_single_astring_from_pg(p->pw_pg, 12361f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 12371f6eb021SLiane Praza if (tg == NULL || /* scf_error() was set */ 12381f6eb021SLiane Praza strcmp(tg, SCF_TM_TARGET_DELEGATE) != 0) { 12391f6eb021SLiane Praza scf_pg_destroy(p->pw_pg); 12401f6eb021SLiane Praza p->pw_pg = NULL; 12411f6eb021SLiane Praza if (tg != NULL) { 12421f6eb021SLiane Praza free(tg); 12431f6eb021SLiane Praza tg = NULL; 12441f6eb021SLiane Praza break; 12451f6eb021SLiane Praza } 12461f6eb021SLiane Praza } 12471f6eb021SLiane Praza /*FALLTHROUGH*/ 12481f6eb021SLiane Praza case SCF_WALK_ERROR: 12491f6eb021SLiane Praza goto done; 12501f6eb021SLiane Praza /*NOTREACHED*/ 12511f6eb021SLiane Praza default: 12521f6eb021SLiane Praza assert(0); 12531f6eb021SLiane Praza abort(); 12541f6eb021SLiane Praza } 12551f6eb021SLiane Praza } 12561f6eb021SLiane Praza 12571f6eb021SLiane Praza p->pw_target = SCF_TM_TARGET_ALL; 12581f6eb021SLiane Praza scf_instance_destroy(tmpl_inst); 12591f6eb021SLiane Praza tmpl_inst = _get_global_inst(h); 12601f6eb021SLiane Praza if (tmpl_inst != NULL) { 12611f6eb021SLiane Praza ret = func(NULL, tmpl_inst, p); 12621f6eb021SLiane Praza switch (ret) { 12631f6eb021SLiane Praza case SCF_WALK_NEXT: 12641f6eb021SLiane Praza break; 12651f6eb021SLiane Praza case SCF_WALK_DONE: 12661f6eb021SLiane Praza /* 12671f6eb021SLiane Praza * Check that the template scoping matches and if not, 12681f6eb021SLiane Praza * continue. 12691f6eb021SLiane Praza */ 12701f6eb021SLiane Praza assert(p->pw_pg != NULL); 12711f6eb021SLiane Praza tg = _scf_read_single_astring_from_pg(p->pw_pg, 12721f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 12731f6eb021SLiane Praza if (tg == NULL || /* scf_error() was set */ 12741f6eb021SLiane Praza strcmp(tg, SCF_TM_TARGET_ALL) != 0) { 12751f6eb021SLiane Praza scf_pg_destroy(p->pw_pg); 12761f6eb021SLiane Praza p->pw_pg = NULL; 12771f6eb021SLiane Praza if (tg != NULL) { 12781f6eb021SLiane Praza free(tg); 12791f6eb021SLiane Praza tg = NULL; 12801f6eb021SLiane Praza break; 12811f6eb021SLiane Praza } 12821f6eb021SLiane Praza } 12831f6eb021SLiane Praza /*FALLTHROUGH*/ 12841f6eb021SLiane Praza case SCF_WALK_ERROR: 12851f6eb021SLiane Praza goto done; 12861f6eb021SLiane Praza /*NOTREACHED*/ 12871f6eb021SLiane Praza default: 12881f6eb021SLiane Praza assert(0); 12891f6eb021SLiane Praza abort(); 12901f6eb021SLiane Praza } 12911f6eb021SLiane Praza } 12921f6eb021SLiane Praza 12931f6eb021SLiane Praza done: 12941f6eb021SLiane Praza free(tg); 12951f6eb021SLiane Praza if (ret != SCF_WALK_DONE) 12961f6eb021SLiane Praza scf_instance_destroy(tmpl_inst); 12971f6eb021SLiane Praza p->pw_target = NULL; 12981f6eb021SLiane Praza } 12991f6eb021SLiane Praza 13001f6eb021SLiane Praza /* 13011f6eb021SLiane Praza * _get_pg() returns 0 on success and -1 on failure. Sets scf_error() 13021f6eb021SLiane Praza * on failure. 13031f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 13041f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 13051f6eb021SLiane Praza * SCF_ERROR_DELETED 13061f6eb021SLiane Praza * SCF_ERROR_HANDLE_MISMATCH 13071f6eb021SLiane Praza * SCF_ERROR_INTERNAL 13081f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 13091f6eb021SLiane Praza * name is not a valid property group. 13101f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 13111f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 13121f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 13131f6eb021SLiane Praza * SCF_ERROR_NOT_SET 13141f6eb021SLiane Praza */ 13151f6eb021SLiane Praza static int 13161f6eb021SLiane Praza _get_pg(scf_service_t *svc, scf_instance_t *inst, 13171f6eb021SLiane Praza const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg) 13181f6eb021SLiane Praza { 13191f6eb021SLiane Praza int ret; 13201f6eb021SLiane Praza 13211f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 13221f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 13231f6eb021SLiane Praza assert(pg != NULL); 13241f6eb021SLiane Praza 13251f6eb021SLiane Praza if (inst != NULL) 13261f6eb021SLiane Praza ret = scf_instance_get_pg_composed(inst, snap, name, pg); 13271f6eb021SLiane Praza else 13281f6eb021SLiane Praza ret = scf_service_get_pg(svc, name, pg); 13291f6eb021SLiane Praza 13301f6eb021SLiane Praza return (ret); 13311f6eb021SLiane Praza } 13321f6eb021SLiane Praza 13331f6eb021SLiane Praza /* 13341f6eb021SLiane Praza * Returns SCF_WALK_NEXT for not found, SCF_WALK_ERROR for error, 13351f6eb021SLiane Praza * and SCF_WALK_DONE for found. 13361f6eb021SLiane Praza * On error, destroy pg and set it to NULL. 13371f6eb021SLiane Praza * 13381f6eb021SLiane Praza * Sets scf_error() if SCF_WALK_ERROR is returned to _BACKEND_ACCESS, 13391f6eb021SLiane Praza * _CONNECTION_BROKEN, _INTERNAL, _INVALID_ARGUMENT (name is not a 13401f6eb021SLiane Praza * valid property group), _NO_RESOURCES, or _NOT_BOUND. 13411f6eb021SLiane Praza */ 13421f6eb021SLiane Praza static int 13431f6eb021SLiane Praza _lookup_pg(scf_service_t *svc, scf_instance_t *inst, 13441f6eb021SLiane Praza const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg) 13451f6eb021SLiane Praza { 13461f6eb021SLiane Praza int ret; 13471f6eb021SLiane Praza 13481f6eb021SLiane Praza ret = _get_pg(svc, inst, snap, name, pg); 13491f6eb021SLiane Praza 13501f6eb021SLiane Praza if (ret == 0) { 13511f6eb021SLiane Praza return (SCF_WALK_DONE); 13521f6eb021SLiane Praza } else { 13531f6eb021SLiane Praza switch (scf_error()) { 13541f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 13551f6eb021SLiane Praza case SCF_ERROR_DELETED: 13561f6eb021SLiane Praza return (SCF_WALK_NEXT); 13571f6eb021SLiane Praza 13581f6eb021SLiane Praza case SCF_ERROR_BACKEND_ACCESS: 13591f6eb021SLiane Praza case SCF_ERROR_CONNECTION_BROKEN: 13601f6eb021SLiane Praza case SCF_ERROR_INTERNAL: 13611f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 13621f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 13631f6eb021SLiane Praza case SCF_ERROR_NO_RESOURCES: 13641f6eb021SLiane Praza scf_pg_destroy(pg); 13651f6eb021SLiane Praza pg = NULL; 13661f6eb021SLiane Praza return (SCF_WALK_ERROR); 13671f6eb021SLiane Praza 13681f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 13691f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 13701f6eb021SLiane Praza default: 13711f6eb021SLiane Praza assert(0); 13721f6eb021SLiane Praza abort(); 13731f6eb021SLiane Praza } 13741f6eb021SLiane Praza } 13751f6eb021SLiane Praza 13761f6eb021SLiane Praza /*NOTREACHED*/ 13771f6eb021SLiane Praza } 13781f6eb021SLiane Praza 13791f6eb021SLiane Praza /* 13801f6eb021SLiane Praza * If match, return 0. If no match, return 1. If error, return -1. 13811f6eb021SLiane Praza * On error set scf_error() to _BACKEND_ACCESS, _CONNECTION_BROKEN, 13821f6eb021SLiane Praza * _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, _NO_RESOURCES, _NOT_BOUND, 13831f6eb021SLiane Praza * _NOT_SET (property group specified by pg is not set), _PERMISSION_DENIED, 13841f6eb021SLiane Praza * or _TEMPLATE_INVALID (target property is not SCF_TYPE_ASTRING or has 13851f6eb021SLiane Praza * more than one value). 13861f6eb021SLiane Praza */ 13871f6eb021SLiane Praza static int 13881f6eb021SLiane Praza check_target_match(scf_propertygroup_t *pg, const char *target) 13891f6eb021SLiane Praza { 13901f6eb021SLiane Praza char *pg_target; 13911f6eb021SLiane Praza int ret = 0; 13921f6eb021SLiane Praza 13931f6eb021SLiane Praza pg_target = _scf_read_single_astring_from_pg(pg, 13941f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 13951f6eb021SLiane Praza if (pg_target == NULL) { 13961f6eb021SLiane Praza switch (scf_error()) { 13971f6eb021SLiane Praza case SCF_ERROR_DELETED: 13981f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 13991f6eb021SLiane Praza return (1); 14001f6eb021SLiane Praza 14011f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 14021f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 14031f6eb021SLiane Praza (void) scf_set_error( 14041f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 14051f6eb021SLiane Praza /*FALLTHROUGH*/ 14061f6eb021SLiane Praza 14071f6eb021SLiane Praza case SCF_ERROR_BACKEND_ACCESS: 14081f6eb021SLiane Praza case SCF_ERROR_CONNECTION_BROKEN: 14091f6eb021SLiane Praza case SCF_ERROR_HANDLE_DESTROYED: 14101f6eb021SLiane Praza case SCF_ERROR_INTERNAL: 14111f6eb021SLiane Praza case SCF_ERROR_NO_RESOURCES: 14121f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 14131f6eb021SLiane Praza case SCF_ERROR_PERMISSION_DENIED: 14141f6eb021SLiane Praza return (-1); 14151f6eb021SLiane Praza 14161f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 14171f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 14181f6eb021SLiane Praza default: 14191f6eb021SLiane Praza assert(0); 14201f6eb021SLiane Praza abort(); 14211f6eb021SLiane Praza } 14221f6eb021SLiane Praza /*NOTREACHED*/ 14231f6eb021SLiane Praza } 14241f6eb021SLiane Praza 14251f6eb021SLiane Praza /* For a desired target of 'this', check for 'this' and 'instance'. */ 14261f6eb021SLiane Praza if ((strcmp(target, SCF_TM_TARGET_INSTANCE) == 0 || 14271f6eb021SLiane Praza strcmp(target, SCF_TM_TARGET_THIS) == 0) && 14281f6eb021SLiane Praza (strcmp(pg_target, SCF_TM_TARGET_INSTANCE) == 0 || 14291f6eb021SLiane Praza strcmp(pg_target, SCF_TM_TARGET_THIS) == 0)) { 14301f6eb021SLiane Praza goto cleanup; 14311f6eb021SLiane Praza } 14321f6eb021SLiane Praza 14331f6eb021SLiane Praza if (strcmp(target, SCF_TM_TARGET_DELEGATE) == 0 && 14341f6eb021SLiane Praza strcmp(pg_target, SCF_TM_TARGET_DELEGATE) == 0) { 14351f6eb021SLiane Praza goto cleanup; 14361f6eb021SLiane Praza } 14371f6eb021SLiane Praza 14381f6eb021SLiane Praza if (strcmp(target, SCF_TM_TARGET_ALL) == 0 && 14391f6eb021SLiane Praza strcmp(pg_target, SCF_TM_TARGET_ALL) == 0) { 14401f6eb021SLiane Praza goto cleanup; 14411f6eb021SLiane Praza } 14421f6eb021SLiane Praza 14431f6eb021SLiane Praza ret = 1; 14441f6eb021SLiane Praza cleanup: 14451f6eb021SLiane Praza free(pg_target); 14461f6eb021SLiane Praza return (ret); 14471f6eb021SLiane Praza } 14481f6eb021SLiane Praza 14491f6eb021SLiane Praza /* 14501f6eb021SLiane Praza * Check if a matching template property group exists for each of: 14511f6eb021SLiane Praza * name and type, name only, type only, and completely wildcarded 14521f6eb021SLiane Praza * template. 14531f6eb021SLiane Praza * 14541f6eb021SLiane Praza * Both pg_name and pg_type are optional. 14551f6eb021SLiane Praza * 14561f6eb021SLiane Praza * Returns NULL on failure, sets scf_error(): 14571f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 14581f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 14591f6eb021SLiane Praza * SCF_ERROR_DELETED 14601f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 14611f6eb021SLiane Praza * SCF_ERROR_INTERNAL 14621f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 14631f6eb021SLiane Praza * can't combine the _tmpl_pg_name arguments and get a reasonable 14641f6eb021SLiane Praza * length name, or pg_name is not a valid property group. 14651f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 14661f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 14671f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 14681f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 14691f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 14701f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 14711f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 14721f6eb021SLiane Praza * target property is not SCF_TYPE_ASTRING or has more than one value. 14731f6eb021SLiane Praza */ 14741f6eb021SLiane Praza static scf_propertygroup_t * 14751f6eb021SLiane Praza _find_template_pg_match(scf_service_t *svc, scf_instance_t *inst, 14761f6eb021SLiane Praza const scf_snapshot_t *snap, const char *pg_name, const char *pg_type, 14771f6eb021SLiane Praza const char *target, char **tmpl_pg_name) 14781f6eb021SLiane Praza { 14791f6eb021SLiane Praza int ret, r; 14801f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 14811f6eb021SLiane Praza scf_handle_t *h; 14821f6eb021SLiane Praza scf_iter_t *iter; 14831f6eb021SLiane Praza char *name, *type; 14841f6eb021SLiane Praza 14851f6eb021SLiane Praza assert(inst != NULL || svc != NULL); 14861f6eb021SLiane Praza assert(inst == NULL || svc == NULL); 14871f6eb021SLiane Praza 14881f6eb021SLiane Praza if (inst != NULL) 14891f6eb021SLiane Praza h = scf_instance_handle(inst); 14901f6eb021SLiane Praza else 14911f6eb021SLiane Praza h = scf_service_handle(svc); 14921f6eb021SLiane Praza if (h == NULL) { 14931f6eb021SLiane Praza return (NULL); 14941f6eb021SLiane Praza } 14951f6eb021SLiane Praza 14961f6eb021SLiane Praza if ((pg = scf_pg_create(h)) == NULL || 14971f6eb021SLiane Praza (iter = scf_iter_create(h)) == NULL) { 14981f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 14991f6eb021SLiane Praza scf_pg_destroy(pg); 15001f6eb021SLiane Praza return (NULL); 15011f6eb021SLiane Praza } 15021f6eb021SLiane Praza 15031f6eb021SLiane Praza /* 15041f6eb021SLiane Praza * We're going to walk through the possible pg templates that 15051f6eb021SLiane Praza * could match the supplied name and type. We do this 15061f6eb021SLiane Praza * by explicit name lookups when possible to avoid having to 15071f6eb021SLiane Praza * keep track of a most-explicit-match during iteration. 15081f6eb021SLiane Praza */ 15091f6eb021SLiane Praza 15101f6eb021SLiane Praza /* First look for a template with name and type set and matching. */ 15111f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(pg_name, pg_type, 1); 15121f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 15131f6eb021SLiane Praza goto fail; 15141f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 15151f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 15161f6eb021SLiane Praza if (pg != NULL) { 15171f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 15181f6eb021SLiane Praza goto done; 15191f6eb021SLiane Praza else if (r == -1) 15201f6eb021SLiane Praza goto fail; 15211f6eb021SLiane Praza } else { 15221f6eb021SLiane Praza goto done; 15231f6eb021SLiane Praza } 15241f6eb021SLiane Praza } 15251f6eb021SLiane Praza free(*tmpl_pg_name); 15261f6eb021SLiane Praza 15271f6eb021SLiane Praza /* 15281f6eb021SLiane Praza * Need to search on a name-only match before searching on 15291f6eb021SLiane Praza * type matches. 15301f6eb021SLiane Praza */ 15311f6eb021SLiane Praza 15321f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(pg_name, NULL, 0); 15331f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 15341f6eb021SLiane Praza goto fail; 15351f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 15361f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 15371f6eb021SLiane Praza if (pg != NULL) { 15381f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 15391f6eb021SLiane Praza goto done; 15401f6eb021SLiane Praza else if (r == -1) 15411f6eb021SLiane Praza goto fail; 15421f6eb021SLiane Praza } else { 15431f6eb021SLiane Praza goto done; 15441f6eb021SLiane Praza } 15451f6eb021SLiane Praza } 15461f6eb021SLiane Praza free(*tmpl_pg_name); 15471f6eb021SLiane Praza 15481f6eb021SLiane Praza /* Next, see if there's an "nt" template where the type matches. */ 15491f6eb021SLiane Praza if (pg_type != NULL && pg_name == NULL) { 15501f6eb021SLiane Praza if (inst != NULL) 15511f6eb021SLiane Praza ret = scf_iter_instance_pgs_typed_composed(iter, inst, 15521f6eb021SLiane Praza snap, SCF_GROUP_TEMPLATE_PG_PATTERN); 15531f6eb021SLiane Praza else 15541f6eb021SLiane Praza ret = scf_iter_service_pgs_typed(iter, svc, 15551f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN); 15561f6eb021SLiane Praza 15571f6eb021SLiane Praza if (ret != 0) { 15581f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 15591f6eb021SLiane Praza goto fail; 15601f6eb021SLiane Praza } else { 15611f6eb021SLiane Praza assert(0); 15621f6eb021SLiane Praza abort(); 15631f6eb021SLiane Praza } 15641f6eb021SLiane Praza } 15651f6eb021SLiane Praza 15661f6eb021SLiane Praza while ((ret = scf_iter_next_pg(iter, pg)) == 1) { 15671f6eb021SLiane Praza /* Make sure this is a name and type specified pg. */ 15681f6eb021SLiane Praza name = _scf_read_single_astring_from_pg(pg, 15691f6eb021SLiane Praza SCF_PROPERTY_TM_NAME); 15701f6eb021SLiane Praza if (name == NULL) 15711f6eb021SLiane Praza continue; 15721f6eb021SLiane Praza type = _scf_read_single_astring_from_pg(pg, 15731f6eb021SLiane Praza SCF_PROPERTY_TM_TYPE); 15741f6eb021SLiane Praza if (type == NULL) { 15751f6eb021SLiane Praza free(name); 15761f6eb021SLiane Praza continue; 15771f6eb021SLiane Praza } 15781f6eb021SLiane Praza if (strcmp(pg_type, type) == 0 && 15791f6eb021SLiane Praza check_target_match(pg, target) == 0) { 15801f6eb021SLiane Praza *tmpl_pg_name = name; 15811f6eb021SLiane Praza free(type); 15821f6eb021SLiane Praza goto done; 15831f6eb021SLiane Praza } 15841f6eb021SLiane Praza free(type); 15851f6eb021SLiane Praza free(name); 15861f6eb021SLiane Praza } 15871f6eb021SLiane Praza if (ret == -1) { 15881f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 15891f6eb021SLiane Praza goto fail; 15901f6eb021SLiane Praza } else { 15911f6eb021SLiane Praza assert(0); 15921f6eb021SLiane Praza abort(); 15931f6eb021SLiane Praza } 15941f6eb021SLiane Praza } 15951f6eb021SLiane Praza } 15961f6eb021SLiane Praza 15971f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(NULL, pg_type, 0); 15981f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 15991f6eb021SLiane Praza goto fail; 16001f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 16011f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 16021f6eb021SLiane Praza if (pg != NULL) { 16031f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 16041f6eb021SLiane Praza goto done; 16051f6eb021SLiane Praza else if (r == -1) 16061f6eb021SLiane Praza goto fail; 16071f6eb021SLiane Praza } else { 16081f6eb021SLiane Praza goto done; 16091f6eb021SLiane Praza } 16101f6eb021SLiane Praza } 16111f6eb021SLiane Praza free(*tmpl_pg_name); 16121f6eb021SLiane Praza 16131f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(NULL, NULL, 0); 16141f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 16151f6eb021SLiane Praza goto fail; 16161f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 16171f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 16181f6eb021SLiane Praza if (pg != NULL) { 16191f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 16201f6eb021SLiane Praza goto done; 16211f6eb021SLiane Praza else if (r == -1) 16221f6eb021SLiane Praza goto fail; 16231f6eb021SLiane Praza } else { 16241f6eb021SLiane Praza goto done; 16251f6eb021SLiane Praza } 16261f6eb021SLiane Praza } 16271f6eb021SLiane Praza 16281f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 16291f6eb021SLiane Praza fail: 16301f6eb021SLiane Praza scf_pg_destroy(pg); 16311f6eb021SLiane Praza if (*tmpl_pg_name != NULL) 16321f6eb021SLiane Praza free(*tmpl_pg_name); 16331f6eb021SLiane Praza *tmpl_pg_name = NULL; 16341f6eb021SLiane Praza pg = NULL; 16351f6eb021SLiane Praza done: 16361f6eb021SLiane Praza if (ret == SCF_WALK_ERROR) 16371f6eb021SLiane Praza free(*tmpl_pg_name); 16381f6eb021SLiane Praza scf_iter_destroy(iter); 16391f6eb021SLiane Praza return (pg); 16401f6eb021SLiane Praza } 16411f6eb021SLiane Praza 16421f6eb021SLiane Praza /* 16431f6eb021SLiane Praza * Finds the pg match in either the supplied service or instance. 16441f6eb021SLiane Praza * Returns SCF_WALK_ERROR, SCF_WALK_NEXT, or SCF_WALK_DONE. 16451f6eb021SLiane Praza * If returning SCF_WALK_ERROR, sets scf_error(): 16461f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 16471f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 16481f6eb021SLiane Praza * SCF_ERROR_DELETED 16491f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 16501f6eb021SLiane Praza * SCF_ERROR_INTERNAL 16511f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 16521f6eb021SLiane Praza * The snaphot is not a valid snapshot name, 16531f6eb021SLiane Praza * or can't create a reasonable property group template name. 16541f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 16551f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 16561f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 16571f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 16581f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 16591f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 16601f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 16611f6eb021SLiane Praza * target property is not SCF_TYPE_ASTRING or has more than one value. 16621f6eb021SLiane Praza */ 16631f6eb021SLiane Praza static int 16641f6eb021SLiane Praza find_pg_match(scf_service_t *svc, scf_instance_t *inst, pg_tmpl_walk_t *p) 16651f6eb021SLiane Praza { 16661f6eb021SLiane Praza scf_snapshot_t *tmpl_snap = NULL; 16671f6eb021SLiane Praza scf_propertygroup_t *pg; 16681f6eb021SLiane Praza scf_handle_t *h; 16691f6eb021SLiane Praza char *tmpl_pg_name; 16701f6eb021SLiane Praza 16711f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 16721f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 16731f6eb021SLiane Praza 16741f6eb021SLiane Praza if (inst != NULL) 16751f6eb021SLiane Praza h = scf_instance_handle(inst); 16761f6eb021SLiane Praza else 16771f6eb021SLiane Praza h = scf_service_handle(svc); 16781f6eb021SLiane Praza if (h == NULL) 16791f6eb021SLiane Praza return (SCF_WALK_ERROR); 16801f6eb021SLiane Praza 16811f6eb021SLiane Praza if (p->pw_snapname != NULL) { 16821f6eb021SLiane Praza if (_get_snapshot(inst, p->pw_snapname, &tmpl_snap) == -1) 16831f6eb021SLiane Praza return (SCF_WALK_ERROR); 16841f6eb021SLiane Praza } 16851f6eb021SLiane Praza pg = _find_template_pg_match(svc, inst, tmpl_snap, p->pw_pgname, 16861f6eb021SLiane Praza p->pw_pgtype, p->pw_target, &tmpl_pg_name); 16871f6eb021SLiane Praza 16881f6eb021SLiane Praza if (pg != NULL) { 16891f6eb021SLiane Praza p->pw_snap = tmpl_snap; 16901f6eb021SLiane Praza p->pw_pg = pg; 16911f6eb021SLiane Praza p->pw_tmpl_pgname = tmpl_pg_name; 16921f6eb021SLiane Praza p->pw_inst = inst; 16931f6eb021SLiane Praza p->pw_svc = svc; 16941f6eb021SLiane Praza return (SCF_WALK_DONE); 16951f6eb021SLiane Praza } 16961f6eb021SLiane Praza 16971f6eb021SLiane Praza scf_snapshot_destroy(tmpl_snap); 16981f6eb021SLiane Praza return (SCF_WALK_NEXT); 16991f6eb021SLiane Praza } 17001f6eb021SLiane Praza 17011f6eb021SLiane Praza /* 17021f6eb021SLiane Praza * return 0 on success and -1 on failure. 17031f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 17041f6eb021SLiane Praza * SCF_ERROR_DELETED 17051f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 17061f6eb021SLiane Praza * SCF_ERROR_HANDLE_MISMATCH 17071f6eb021SLiane Praza * SCF_ERROR_INTERNAL 17081f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 17091f6eb021SLiane Praza * FMRI argument, snapshot name, pg_name, or pg is invalid. 17101f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 17111f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 17121f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 17131f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 17141f6eb021SLiane Praza * SCF_ERROR_NOT_SET 17151f6eb021SLiane Praza */ 17161f6eb021SLiane Praza int 17171f6eb021SLiane Praza scf_tmpl_get_by_pg(scf_propertygroup_t *pg, scf_pg_tmpl_t *pg_tmpl, int flags) 17181f6eb021SLiane Praza { 17191f6eb021SLiane Praza char *fmribuf = NULL, *snapbuf = NULL, *pg_name = NULL, *pg_type = NULL; 172076fa7285SAntonello Cruz int ret; 17211f6eb021SLiane Praza ssize_t fbufsz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1; 17221f6eb021SLiane Praza ssize_t nbufsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 17231f6eb021SLiane Praza ssize_t tbufsz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1; 17241f6eb021SLiane Praza scf_instance_t *inst = NULL; 17251f6eb021SLiane Praza scf_snaplevel_t *snaplvl = NULL; 17261f6eb021SLiane Praza scf_service_t *svc = NULL; 17271f6eb021SLiane Praza scf_handle_t *h; 17281f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 172976fa7285SAntonello Cruz pg_tmpl_walk_t *p = NULL; 17301f6eb021SLiane Praza 17311f6eb021SLiane Praza assert(fbufsz != 0 && nbufsz != 0 && tbufsz != 0); 17321f6eb021SLiane Praza 17331f6eb021SLiane Praza scf_tmpl_pg_reset(pg_tmpl); 17341f6eb021SLiane Praza 17351f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) 17361f6eb021SLiane Praza return (-1); 17371f6eb021SLiane Praza 17381f6eb021SLiane Praza if ((inst = scf_instance_create(h)) == NULL || 17391f6eb021SLiane Praza (svc = scf_service_create(h)) == NULL || 17401f6eb021SLiane Praza (snaplvl = scf_snaplevel_create(h)) == NULL) { 174176fa7285SAntonello Cruz goto fail; 17421f6eb021SLiane Praza } 17431f6eb021SLiane Praza 17441f6eb021SLiane Praza if ((fmribuf = malloc(fbufsz)) == NULL || 17451f6eb021SLiane Praza (pg_name = malloc(nbufsz)) == NULL || 17461f6eb021SLiane Praza (pg_type = malloc(tbufsz)) == NULL || 17471f6eb021SLiane Praza (p = calloc(1, sizeof (pg_tmpl_walk_t))) == NULL) { 17481f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 174976fa7285SAntonello Cruz goto fail; 17501f6eb021SLiane Praza } 17511f6eb021SLiane Praza 17521f6eb021SLiane Praza if (scf_pg_get_name(pg, pg_name, nbufsz) < 0) { 17531f6eb021SLiane Praza goto fail; 17541f6eb021SLiane Praza } 17551f6eb021SLiane Praza 17561f6eb021SLiane Praza if (scf_pg_get_type(pg, pg_type, tbufsz) < 0) { 17571f6eb021SLiane Praza goto fail; 17581f6eb021SLiane Praza } 17591f6eb021SLiane Praza p->pw_pgname = pg_name; 17601f6eb021SLiane Praza p->pw_pgtype = pg_type; 17611f6eb021SLiane Praza 17621f6eb021SLiane Praza ret = scf_pg_get_parent_snaplevel(pg, snaplvl); 17631f6eb021SLiane Praza if (ret == -1) { 17641f6eb021SLiane Praza switch (scf_error()) { 17651f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 17661f6eb021SLiane Praza /* Parent type doesn't match. Keep looking. */ 17671f6eb021SLiane Praza break; 17681f6eb021SLiane Praza 17691f6eb021SLiane Praza case SCF_ERROR_DELETED: 17701f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 17711f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 17721f6eb021SLiane Praza /* Pass these back to the caller. */ 17731f6eb021SLiane Praza goto fail; 17741f6eb021SLiane Praza 17751f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 17761f6eb021SLiane Praza default: 17771f6eb021SLiane Praza assert(0); 17781f6eb021SLiane Praza abort(); 17791f6eb021SLiane Praza } 17801f6eb021SLiane Praza 17811f6eb021SLiane Praza /* 17821f6eb021SLiane Praza * No snapshot. We'll use 'editing' by default since 17831f6eb021SLiane Praza * snap and snapbuf are NULL. 17841f6eb021SLiane Praza */ 17851f6eb021SLiane Praza p->pw_snapname = NULL; 17861f6eb021SLiane Praza 17871f6eb021SLiane Praza } else { 17881f6eb021SLiane Praza if ((snap = scf_snapshot_create(h)) == NULL) { 17891f6eb021SLiane Praza goto fail; 17901f6eb021SLiane Praza } 17911f6eb021SLiane Praza 17921f6eb021SLiane Praza ret = scf_snaplevel_get_parent(snaplvl, snap); 17931f6eb021SLiane Praza if (ret == -1) { 17941f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 17951f6eb021SLiane Praza goto fail; 17961f6eb021SLiane Praza } else { 17971f6eb021SLiane Praza assert(0); 17981f6eb021SLiane Praza abort(); 17991f6eb021SLiane Praza } 18001f6eb021SLiane Praza } 18011f6eb021SLiane Praza 18021f6eb021SLiane Praza /* Grab snapshot name while we're here. */ 18031f6eb021SLiane Praza if ((snapbuf = malloc(nbufsz)) == NULL) { 18041f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 18051f6eb021SLiane Praza goto fail; 18061f6eb021SLiane Praza } 18071f6eb021SLiane Praza if (scf_snapshot_get_name(snap, snapbuf, nbufsz) < 0) { 18081f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 18091f6eb021SLiane Praza goto fail; 18101f6eb021SLiane Praza } else { 18111f6eb021SLiane Praza assert(0); 18121f6eb021SLiane Praza abort(); 18131f6eb021SLiane Praza } 18141f6eb021SLiane Praza } 18151f6eb021SLiane Praza p->pw_snapname = snapbuf; 18161f6eb021SLiane Praza 18171f6eb021SLiane Praza ret = scf_snapshot_get_parent(snap, inst); 18181f6eb021SLiane Praza if (ret == -1) { 18191f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 18201f6eb021SLiane Praza goto fail; 18211f6eb021SLiane Praza } else { 18221f6eb021SLiane Praza assert(0); 18231f6eb021SLiane Praza abort(); 18241f6eb021SLiane Praza } 18251f6eb021SLiane Praza } 18261f6eb021SLiane Praza 18271f6eb021SLiane Praza _walk_template_instances(NULL, inst, snap, 18281f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, p, flags); 18291f6eb021SLiane Praza } 18301f6eb021SLiane Praza 18311f6eb021SLiane Praza /* No snapshot parent. Go looking for instance parent. */ 18321f6eb021SLiane Praza if (snapbuf == NULL) { 18331f6eb021SLiane Praza /* First look for instance parent. */ 18341f6eb021SLiane Praza ret = scf_pg_get_parent_instance(pg, inst); 18351f6eb021SLiane Praza if (ret == 0) { 18361f6eb021SLiane Praza _walk_template_instances(NULL, inst, snap, 18371f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, 18381f6eb021SLiane Praza p, flags); 18391f6eb021SLiane Praza /* OK, check for service parent */ 18401f6eb021SLiane Praza } else if (ret == -1 && 18411f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 18421f6eb021SLiane Praza ret = scf_pg_get_parent_service(pg, svc); 18431f6eb021SLiane Praza if (ret == 0) { 18441f6eb021SLiane Praza _walk_template_instances(svc, NULL, snap, 18451f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, 18461f6eb021SLiane Praza p, flags); 18471f6eb021SLiane Praza } else { 18481f6eb021SLiane Praza switch (scf_error()) { 18491f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 18501f6eb021SLiane Praza (void) scf_set_error( 18511f6eb021SLiane Praza SCF_ERROR_NOT_FOUND); 18521f6eb021SLiane Praza /*FALLTHROUGH*/ 18531f6eb021SLiane Praza 18541f6eb021SLiane Praza case SCF_ERROR_CONNECTION_BROKEN: 18551f6eb021SLiane Praza case SCF_ERROR_DELETED: 18561f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 18571f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 18581f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 18591f6eb021SLiane Praza goto fail; 18601f6eb021SLiane Praza 18611f6eb021SLiane Praza default: 18621f6eb021SLiane Praza assert(0); 18631f6eb021SLiane Praza abort(); 18641f6eb021SLiane Praza } 18651f6eb021SLiane Praza } 18661f6eb021SLiane Praza } else { 18671f6eb021SLiane Praza goto fail; 18681f6eb021SLiane Praza } 18691f6eb021SLiane Praza } 18701f6eb021SLiane Praza 18711f6eb021SLiane Praza if (p->pw_pg != NULL) { 18721f6eb021SLiane Praza pg_tmpl->pt_h = h; 18731f6eb021SLiane Praza pg_tmpl->pt_pg = p->pw_pg; 18741f6eb021SLiane Praza pg_tmpl->pt_inst = p->pw_inst; 187576fa7285SAntonello Cruz /* we may get a different instance back */ 187676fa7285SAntonello Cruz if (p->pw_inst != inst) 187776fa7285SAntonello Cruz scf_instance_destroy(inst); 18781f6eb021SLiane Praza pg_tmpl->pt_snap = p->pw_snap; 18791f6eb021SLiane Praza pg_tmpl->pt_svc = p->pw_svc; 188076fa7285SAntonello Cruz /* we may get a different service back */ 188176fa7285SAntonello Cruz if (p->pw_svc != svc) 188276fa7285SAntonello Cruz scf_service_destroy(svc); 18831f6eb021SLiane Praza pg_tmpl->pt_populated = 1; 18841f6eb021SLiane Praza free(p->pw_tmpl_pgname); 18851f6eb021SLiane Praza ret = 0; 18861f6eb021SLiane Praza goto done; 18871f6eb021SLiane Praza } 18881f6eb021SLiane Praza 18891f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 18901f6eb021SLiane Praza 18911f6eb021SLiane Praza fail: 189276fa7285SAntonello Cruz ret = -1; 18931f6eb021SLiane Praza scf_instance_destroy(inst); 18941f6eb021SLiane Praza scf_service_destroy(svc); 18951f6eb021SLiane Praza done: 189676fa7285SAntonello Cruz scf_snapshot_destroy(snap); 18971f6eb021SLiane Praza free(snapbuf); 18981f6eb021SLiane Praza free(fmribuf); 18991f6eb021SLiane Praza free(pg_name); 19001f6eb021SLiane Praza free(pg_type); 19011f6eb021SLiane Praza free(p); 19021f6eb021SLiane Praza scf_snaplevel_destroy(snaplvl); 19031f6eb021SLiane Praza return (ret); 19041f6eb021SLiane Praza } 19051f6eb021SLiane Praza 19061f6eb021SLiane Praza /* 19071f6eb021SLiane Praza * int scf_tmpl_get_by_pg_name() 19081f6eb021SLiane Praza * 19091f6eb021SLiane Praza * Get a template by a combination of the name and type. Either name 19101f6eb021SLiane Praza * or type can be null, which indicates a wildcard. flags may be 19111f6eb021SLiane Praza * SCF_PG_TMPL_FLAG_CURRENT (use current properties rather than 19121f6eb021SLiane Praza * the defined or running snapshot), and SCF_PG_TMPL_FLAG_EXACT (match 19131f6eb021SLiane Praza * only templates defined by the FMRI in question, not by its restarter 19141f6eb021SLiane Praza * or globally). Returns 0 on success and -1 on error, and sets 19151f6eb021SLiane Praza * scf_error() to: 19161f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 19171f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 19181f6eb021SLiane Praza * The connection to the repository was lost. 19191f6eb021SLiane Praza * SCF_ERROR_DELETED 19201f6eb021SLiane Praza * The instance has been deleted. 19211f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 19221f6eb021SLiane Praza * SCF_ERROR_INTERNAL 19231f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 19241f6eb021SLiane Praza * FMRI isn't valid, pg_name is too long to look for a template, or 19251f6eb021SLiane Praza * snapshot specified isn't a valid name 19261f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 19271f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 19281f6eb021SLiane Praza * The server does not have adequate resources to complete the request. 19291f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 19301f6eb021SLiane Praza * The handle is not currently bound. 19311f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 19321f6eb021SLiane Praza * Object matching FMRI doesn't exist in the repository, or snapshot 19331f6eb021SLiane Praza * doesn't exist. 19341f6eb021SLiane Praza */ 19351f6eb021SLiane Praza int 19361f6eb021SLiane Praza scf_tmpl_get_by_pg_name(const char *fmri, const char *snapshot, 19371f6eb021SLiane Praza const char *pg_name, const char *pg_type, scf_pg_tmpl_t *pg_tmpl, int flags) 19381f6eb021SLiane Praza { 19391f6eb021SLiane Praza scf_instance_t *inst = NULL; 19401f6eb021SLiane Praza scf_service_t *svc = NULL; 19411f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 194276fa7285SAntonello Cruz pg_tmpl_walk_t *p = NULL; 19431f6eb021SLiane Praza scf_handle_t *h; 19441f6eb021SLiane Praza int ret; 19451f6eb021SLiane Praza 19461f6eb021SLiane Praza assert(pg_tmpl != NULL); 19471f6eb021SLiane Praza h = pg_tmpl->pt_h; 19481f6eb021SLiane Praza assert(h != NULL); 19491f6eb021SLiane Praza 19501f6eb021SLiane Praza scf_tmpl_pg_reset(pg_tmpl); 19511f6eb021SLiane Praza 19521f6eb021SLiane Praza if ((inst = scf_instance_create(h)) == NULL || 19531f6eb021SLiane Praza (svc = scf_service_create(h)) == NULL) { 195476fa7285SAntonello Cruz goto fail; 19551f6eb021SLiane Praza } 19561f6eb021SLiane Praza 19571f6eb021SLiane Praza p = calloc(1, sizeof (pg_tmpl_walk_t)); 19581f6eb021SLiane Praza if (p == NULL) { 19591f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 196076fa7285SAntonello Cruz goto fail; 19611f6eb021SLiane Praza } 19621f6eb021SLiane Praza 19631f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, 19641f6eb021SLiane Praza NULL, SCF_DECODE_FMRI_EXACT); 19651f6eb021SLiane Praza if (ret == 0) { 19661f6eb021SLiane Praza scf_service_destroy(svc); 19671f6eb021SLiane Praza svc = NULL; 19681f6eb021SLiane Praza } else if (ret != 0 && 19691f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 19701f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, svc, 19711f6eb021SLiane Praza NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT); 19721f6eb021SLiane Praza if (ret == 0) { 19731f6eb021SLiane Praza scf_instance_destroy(inst); 19741f6eb021SLiane Praza inst = NULL; 19751f6eb021SLiane Praza } 19761f6eb021SLiane Praza } 19771f6eb021SLiane Praza if (ret != 0) { 19781f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 19791f6eb021SLiane Praza goto fail; 19801f6eb021SLiane Praza } else switch (scf_error()) { 19811f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 19821f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 19831f6eb021SLiane Praza goto fail; 19841f6eb021SLiane Praza 19851f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 19861f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 19871f6eb021SLiane Praza goto fail; 19881f6eb021SLiane Praza 19891f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 19901f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 19911f6eb021SLiane Praza default: 19921f6eb021SLiane Praza assert(0); 19931f6eb021SLiane Praza abort(); 19941f6eb021SLiane Praza } 19951f6eb021SLiane Praza } 19961f6eb021SLiane Praza 19971f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 19981f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 19991f6eb021SLiane Praza 200076fa7285SAntonello Cruz /* If we have a service fmri, snapshot is ignored. */ 20011f6eb021SLiane Praza if (inst != NULL) { 20021f6eb021SLiane Praza if (snapshot == NULL || strcmp(snapshot, "running") == 0 || 20031f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_CURRENT) == 20041f6eb021SLiane Praza SCF_PG_TMPL_FLAG_CURRENT) { 20051f6eb021SLiane Praza if (_get_snapshot(inst, NULL, &snap) == -1) 20061f6eb021SLiane Praza goto fail; 20071f6eb021SLiane Praza } else { 20081f6eb021SLiane Praza if (_get_snapshot(inst, snapshot, &snap) == -1) { 20091f6eb021SLiane Praza goto fail; 20101f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 20111f6eb021SLiane Praza goto fail; 20121f6eb021SLiane Praza } 20131f6eb021SLiane Praza } 20141f6eb021SLiane Praza } 20151f6eb021SLiane Praza 20161f6eb021SLiane Praza p->pw_snapname = snapshot; 20171f6eb021SLiane Praza p->pw_pgname = pg_name; 20181f6eb021SLiane Praza p->pw_pgtype = pg_type; 20191f6eb021SLiane Praza 20201f6eb021SLiane Praza /* 20211f6eb021SLiane Praza * For each of instance, restarter, global 20221f6eb021SLiane Praza * - check for a tm_pg_pattern_nt_<name> matching type 20231f6eb021SLiane Praza * - check for a tm_pg_pattern_t_<type> matching type 20241f6eb021SLiane Praza * - check for any tm_pg_pattern_ 20251f6eb021SLiane Praza * Currently plan to return the most specific match only. 20261f6eb021SLiane Praza */ 20271f6eb021SLiane Praza _walk_template_instances(svc, inst, snap, 20281f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, p, flags); 20291f6eb021SLiane Praza 20301f6eb021SLiane Praza if (p->pw_pg != NULL) { 20311f6eb021SLiane Praza pg_tmpl->pt_h = h; 20321f6eb021SLiane Praza pg_tmpl->pt_pg = p->pw_pg; 20331f6eb021SLiane Praza pg_tmpl->pt_inst = p->pw_inst; 203476fa7285SAntonello Cruz /* we may get a different instance back */ 203576fa7285SAntonello Cruz if (p->pw_inst != inst) 203676fa7285SAntonello Cruz scf_instance_destroy(inst); 20371f6eb021SLiane Praza pg_tmpl->pt_snap = p->pw_snap; 20381f6eb021SLiane Praza pg_tmpl->pt_svc = p->pw_svc; 203976fa7285SAntonello Cruz /* we may get a different service back */ 204076fa7285SAntonello Cruz if (p->pw_svc != svc) 204176fa7285SAntonello Cruz scf_service_destroy(svc); 20421f6eb021SLiane Praza pg_tmpl->pt_populated = 1; 204376fa7285SAntonello Cruz scf_snapshot_destroy(snap); 20441f6eb021SLiane Praza free(p->pw_tmpl_pgname); 20451f6eb021SLiane Praza free(p); 20461f6eb021SLiane Praza return (0); 20471f6eb021SLiane Praza } 20481f6eb021SLiane Praza 20491f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 20501f6eb021SLiane Praza fail: 20511f6eb021SLiane Praza free(p); 20521f6eb021SLiane Praza scf_instance_destroy(inst); 20531f6eb021SLiane Praza scf_service_destroy(svc); 20541f6eb021SLiane Praza scf_snapshot_destroy(snap); 20551f6eb021SLiane Praza return (-1); 20561f6eb021SLiane Praza } 20571f6eb021SLiane Praza 20581f6eb021SLiane Praza /* 20591f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _CONNECTION_BROKEN, 20601f6eb021SLiane Praza * _DELETED, _NO_RESOURCES, or _NOT_BOUND. 20611f6eb021SLiane Praza */ 20621f6eb021SLiane Praza static scf_iter_t * 20631f6eb021SLiane Praza _get_svc_or_inst_iter(scf_handle_t *h, scf_pg_tmpl_t *t) 20641f6eb021SLiane Praza { 20651f6eb021SLiane Praza scf_iter_t *iter; 20661f6eb021SLiane Praza int ret; 20671f6eb021SLiane Praza 20681f6eb021SLiane Praza assert(t->pt_svc != NULL || t->pt_inst != NULL); 20691f6eb021SLiane Praza assert(t->pt_svc == NULL || t->pt_inst == NULL); 20701f6eb021SLiane Praza 20711f6eb021SLiane Praza if ((iter = scf_iter_create(h)) == NULL) { 20721f6eb021SLiane Praza return (NULL); 20731f6eb021SLiane Praza } 20741f6eb021SLiane Praza 20751f6eb021SLiane Praza /* Iterate on property groups of type template_pg_pattern */ 20761f6eb021SLiane Praza 20771f6eb021SLiane Praza if (t->pt_inst != NULL) 20781f6eb021SLiane Praza ret = scf_iter_instance_pgs_typed_composed(iter, 20791f6eb021SLiane Praza t->pt_inst, t->pt_snap, 20801f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN); 20811f6eb021SLiane Praza if (t->pt_svc != NULL) 20821f6eb021SLiane Praza ret = scf_iter_service_pgs_typed(iter, t->pt_svc, 20831f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN); 20841f6eb021SLiane Praza 20851f6eb021SLiane Praza if (ret != 0) { 20861f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 20871f6eb021SLiane Praza scf_iter_destroy(iter); 20881f6eb021SLiane Praza return (NULL); 20891f6eb021SLiane Praza } else { 20901f6eb021SLiane Praza assert(0); 20911f6eb021SLiane Praza abort(); 20921f6eb021SLiane Praza } 20931f6eb021SLiane Praza } 20941f6eb021SLiane Praza 20951f6eb021SLiane Praza return (iter); 20961f6eb021SLiane Praza } 20971f6eb021SLiane Praza 20981f6eb021SLiane Praza /* 20991f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 21001f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 21011f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 21021f6eb021SLiane Praza * SCF_ERROR_DELETED 21031f6eb021SLiane Praza * SCF_HANDLE_DESTROYED 21041f6eb021SLiane Praza * SCF_ERROR_INTERNAL 21051f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 21061f6eb021SLiane Praza * Handle argument is NULL, or snaphot is not a valid snapshot name. 21071f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 21081f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 21091f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 21101f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 21111f6eb021SLiane Praza */ 21121f6eb021SLiane Praza static scf_iter_t * 21131f6eb021SLiane Praza _get_next_iterator(scf_handle_t *h, scf_pg_tmpl_t *t, const char *snapshot, 21141f6eb021SLiane Praza int exact) 21151f6eb021SLiane Praza { 21161f6eb021SLiane Praza scf_iter_t *iter = NULL; 21171f6eb021SLiane Praza ssize_t limit; 21181f6eb021SLiane Praza 21191f6eb021SLiane Praza limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 21201f6eb021SLiane Praza assert(limit != 0); 21211f6eb021SLiane Praza 21221f6eb021SLiane Praza /* 21231f6eb021SLiane Praza * Check what level we last iterated on: none, service, 21241f6eb021SLiane Praza * restarter, or global. Make sure that if one in the middle 21251f6eb021SLiane Praza * doesn't exist, we move on to the next entity. 212676fa7285SAntonello Cruz * 212776fa7285SAntonello Cruz * Before we drop any references to pt_inst or pt_svc we must 212876fa7285SAntonello Cruz * destroy them so we don't leak them. 21291f6eb021SLiane Praza */ 21301f6eb021SLiane Praza do { 21311f6eb021SLiane Praza switch (t->pt_iter_last) { 21321f6eb021SLiane Praza case SCF__TMPL_ITER_NONE: 21331f6eb021SLiane Praza t->pt_iter_last = SCF__TMPL_ITER_INST; 213476fa7285SAntonello Cruz if (t->pt_inst != t->pt_orig_inst) 213576fa7285SAntonello Cruz scf_instance_destroy(t->pt_inst); 21361f6eb021SLiane Praza t->pt_inst = t->pt_orig_inst; 213776fa7285SAntonello Cruz if (t->pt_svc != t->pt_orig_svc) 213876fa7285SAntonello Cruz scf_service_destroy(t->pt_svc); 21391f6eb021SLiane Praza t->pt_svc = t->pt_orig_svc; 21401f6eb021SLiane Praza break; 21411f6eb021SLiane Praza 21421f6eb021SLiane Praza case SCF__TMPL_ITER_INST: 21431f6eb021SLiane Praza /* 21441f6eb021SLiane Praza * Don't go any further than the specified instance 21451f6eb021SLiane Praza * if exact was set. 21461f6eb021SLiane Praza */ 21471f6eb021SLiane Praza if (exact == 1) { 21481f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 21491f6eb021SLiane Praza goto fail; 21501f6eb021SLiane Praza } 21511f6eb021SLiane Praza t->pt_iter_last = SCF__TMPL_ITER_RESTARTER; 215276fa7285SAntonello Cruz if (t->pt_inst != t->pt_orig_inst) 215376fa7285SAntonello Cruz scf_instance_destroy(t->pt_inst); 21541f6eb021SLiane Praza t->pt_inst = _get_restarter_inst(h, t->pt_orig_svc, 21551f6eb021SLiane Praza t->pt_orig_inst, t->pt_snap); 2156*a58a7fedSMilan Jurik if (t->pt_svc != t->pt_orig_svc) 215776fa7285SAntonello Cruz scf_service_destroy(t->pt_svc); 21581f6eb021SLiane Praza t->pt_svc = NULL; 21591f6eb021SLiane Praza break; 21601f6eb021SLiane Praza 21611f6eb021SLiane Praza case SCF__TMPL_ITER_RESTARTER: 21621f6eb021SLiane Praza t->pt_iter_last = SCF__TMPL_ITER_GLOBAL; 216376fa7285SAntonello Cruz if (t->pt_inst != t->pt_orig_inst) 216476fa7285SAntonello Cruz scf_instance_destroy(t->pt_inst); 21651f6eb021SLiane Praza t->pt_inst = _get_global_inst(h); 2166*a58a7fedSMilan Jurik if (t->pt_svc != t->pt_orig_svc) 216776fa7285SAntonello Cruz scf_service_destroy(t->pt_svc); 21681f6eb021SLiane Praza t->pt_svc = NULL; 21691f6eb021SLiane Praza break; 21701f6eb021SLiane Praza 21711f6eb021SLiane Praza case SCF__TMPL_ITER_GLOBAL: 21721f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 21731f6eb021SLiane Praza return (NULL); 21741f6eb021SLiane Praza 21751f6eb021SLiane Praza default: 21761f6eb021SLiane Praza assert(0); 21771f6eb021SLiane Praza abort(); 21781f6eb021SLiane Praza } 21791f6eb021SLiane Praza } while (t->pt_inst == NULL && t->pt_svc == NULL); 21801f6eb021SLiane Praza 21811f6eb021SLiane Praza /* Set pt_snap to the snapshot for this instance */ 21821f6eb021SLiane Praza if (t->pt_inst != NULL) { 21831f6eb021SLiane Praza scf_snapshot_destroy(t->pt_snap); 21841f6eb021SLiane Praza if (_get_snapshot(t->pt_inst, snapshot, 21851f6eb021SLiane Praza &t->pt_snap) == -1) 21861f6eb021SLiane Praza goto fail; 21871f6eb021SLiane Praza } 21881f6eb021SLiane Praza 21891f6eb021SLiane Praza iter = _get_svc_or_inst_iter(h, t); 21901f6eb021SLiane Praza fail: 21911f6eb021SLiane Praza return (iter); 21921f6eb021SLiane Praza } 21931f6eb021SLiane Praza 21941f6eb021SLiane Praza /* 21951f6eb021SLiane Praza * scf_pg_tmpl_t *scf_tmpl_pg_create(scf_handle_t *) 21961f6eb021SLiane Praza * 21971f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT 21981f6eb021SLiane Praza * or _NO_MEMORY. 21991f6eb021SLiane Praza */ 22001f6eb021SLiane Praza scf_pg_tmpl_t * 22011f6eb021SLiane Praza scf_tmpl_pg_create(scf_handle_t *handle) 22021f6eb021SLiane Praza { 22031f6eb021SLiane Praza scf_pg_tmpl_t *pg_tmpl = NULL; 22041f6eb021SLiane Praza 22051f6eb021SLiane Praza if (handle == NULL) { 22061f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 22071f6eb021SLiane Praza return (NULL); 22081f6eb021SLiane Praza } 22091f6eb021SLiane Praza pg_tmpl = calloc(1, sizeof (scf_pg_tmpl_t)); 22101f6eb021SLiane Praza if (pg_tmpl == NULL) 22111f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 22121f6eb021SLiane Praza else 22131f6eb021SLiane Praza pg_tmpl->pt_h = handle; 22141f6eb021SLiane Praza 22151f6eb021SLiane Praza return (pg_tmpl); 22161f6eb021SLiane Praza } 22171f6eb021SLiane Praza 22181f6eb021SLiane Praza /* 22191f6eb021SLiane Praza * Retrieves name or type of a template pg. 22201f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 22211f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 22221f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 22231f6eb021SLiane Praza * SCF_ERROR_DELETED 22241f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 22251f6eb021SLiane Praza * SCF_ERROR_INTERNAL 22261f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 22271f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 22281f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 22291f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 22301f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 22311f6eb021SLiane Praza * pname property is not SCF_TYPE_ASTRING or has more than one value. 22321f6eb021SLiane Praza */ 22331f6eb021SLiane Praza static ssize_t 22341f6eb021SLiane Praza _scf_tmpl_prop_value(scf_propertygroup_t *pg, const char *pname, char **out) 22351f6eb021SLiane Praza { 22361f6eb021SLiane Praza assert(strcmp(pname, SCF_PROPERTY_TM_NAME) == 0 || 22371f6eb021SLiane Praza strcmp(pname, SCF_PROPERTY_TM_TYPE) == 0); 22381f6eb021SLiane Praza 22391f6eb021SLiane Praza *out = _scf_read_single_astring_from_pg(pg, pname); 22401f6eb021SLiane Praza 22411f6eb021SLiane Praza if (*out != NULL && *out[0] == '\0') { 22421f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 22431f6eb021SLiane Praza free(*out); 22441f6eb021SLiane Praza *out = strdup(SCF_TMPL_WILDCARD); 22451f6eb021SLiane Praza if (*out == NULL) 22461f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 22471f6eb021SLiane Praza } 22481f6eb021SLiane Praza if (*out == NULL) { 22491f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 22501f6eb021SLiane Praza return (-1); 22511f6eb021SLiane Praza } else switch (scf_error()) { 22521f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 22531f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 22541f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 22551f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 22561f6eb021SLiane Praza return (-1); 22571f6eb021SLiane Praza 22581f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 22591f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 22601f6eb021SLiane Praza default: 22611f6eb021SLiane Praza assert(0); 22621f6eb021SLiane Praza abort(); 22631f6eb021SLiane Praza } 22641f6eb021SLiane Praza } 22651f6eb021SLiane Praza 22661f6eb021SLiane Praza return (strlen(*out)); 22671f6eb021SLiane Praza } 22681f6eb021SLiane Praza 22691f6eb021SLiane Praza /* 22701f6eb021SLiane Praza * int scf_tmpl_iter_pgs() 22711f6eb021SLiane Praza * 22721f6eb021SLiane Praza * Iterates through the property group templates for the fmri given. 22731f6eb021SLiane Praza * When t is uninitialized or reset, sets t to the first property group 22741f6eb021SLiane Praza * template in fmri. On subsequent calls, sets t to the next property group 22751f6eb021SLiane Praza * template in frmi. 22761f6eb021SLiane Praza * Returns 1 on success, 0 when no property group templates are left to 22771f6eb021SLiane Praza * iterate, -1 on error. 22781f6eb021SLiane Praza * The flags argument may include SCF_PG_TMPL_FLAG_REQUIRED, 22791f6eb021SLiane Praza * SCF_PG_TMPL_FLAG_CURRENT, and/or SCF_PG_TMPL_FLAG_EXACT. 22801f6eb021SLiane Praza * 22811f6eb021SLiane Praza * Returns -1 on error and sets scf_error() to: 22821f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 22831f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 22841f6eb021SLiane Praza * SCF_ERROR_DELETED 22851f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 22861f6eb021SLiane Praza * SCF_ERROR_INTERNAL 22871f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 22881f6eb021SLiane Praza * The handle argument is NULL, fmri is invalid, or snapshot is invalid. 22891f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 22901f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 22911f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 22921f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 22931f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 22941f6eb021SLiane Praza */ 22951f6eb021SLiane Praza int 22961f6eb021SLiane Praza scf_tmpl_iter_pgs(scf_pg_tmpl_t *t, const char *fmri, const char *snapshot, 22971f6eb021SLiane Praza const char *type, int flags) 22981f6eb021SLiane Praza { 22991f6eb021SLiane Praza scf_handle_t *h; 23001f6eb021SLiane Praza scf_service_t *svc = NULL; 23011f6eb021SLiane Praza scf_instance_t *inst = NULL; 23021f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 23031f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 23041f6eb021SLiane Praza scf_pg_tmpl_t *pg_tmpl = NULL; 23051f6eb021SLiane Praza int err; 23061f6eb021SLiane Praza int found = 0; 23071f6eb021SLiane Praza char *tmpl_type; 23081f6eb021SLiane Praza uint8_t required; 23091f6eb021SLiane Praza int ret; 23101f6eb021SLiane Praza 23111f6eb021SLiane Praza if (t == NULL) { 23121f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 23131f6eb021SLiane Praza return (-1); 23141f6eb021SLiane Praza } 23151f6eb021SLiane Praza 23161f6eb021SLiane Praza h = t->pt_h; 23171f6eb021SLiane Praza 23181f6eb021SLiane Praza if (t->pt_populated == 0) { 23191f6eb021SLiane Praza if ((svc = scf_service_create(h)) == NULL || 23201f6eb021SLiane Praza (inst = scf_instance_create(h)) == NULL || 23211f6eb021SLiane Praza (pg = scf_pg_create(h)) == NULL) { 23221f6eb021SLiane Praza goto fail_non_populated; 23231f6eb021SLiane Praza } 23241f6eb021SLiane Praza 23251f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, 23261f6eb021SLiane Praza NULL, SCF_DECODE_FMRI_EXACT); 23271f6eb021SLiane Praza if (ret == 0) { 23281f6eb021SLiane Praza scf_service_destroy(svc); 23291f6eb021SLiane Praza svc = NULL; 23301f6eb021SLiane Praza } else if (ret != 0 && 23311f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 23321f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, svc, 23331f6eb021SLiane Praza NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT); 23341f6eb021SLiane Praza if (ret == 0) { 23351f6eb021SLiane Praza scf_instance_destroy(inst); 23361f6eb021SLiane Praza inst = NULL; 23371f6eb021SLiane Praza } 23381f6eb021SLiane Praza } 23391f6eb021SLiane Praza 23401f6eb021SLiane Praza if (ret != 0) { 23411f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 23421f6eb021SLiane Praza goto fail_non_populated; 23431f6eb021SLiane Praza } else switch (scf_error()) { 23441f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 23451f6eb021SLiane Praza (void) scf_set_error( 23461f6eb021SLiane Praza SCF_ERROR_INVALID_ARGUMENT); 23471f6eb021SLiane Praza goto fail_non_populated; 23481f6eb021SLiane Praza 23491f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 23501f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 23511f6eb021SLiane Praza goto fail_non_populated; 23521f6eb021SLiane Praza 23531f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 23541f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 23551f6eb021SLiane Praza default: 23561f6eb021SLiane Praza assert(0); 23571f6eb021SLiane Praza abort(); 23581f6eb021SLiane Praza } 23591f6eb021SLiane Praza } 23601f6eb021SLiane Praza 23611f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 23621f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 23631f6eb021SLiane Praza 23641f6eb021SLiane Praza if (inst != NULL) { 23651f6eb021SLiane Praza if (snapshot == NULL || 23661f6eb021SLiane Praza strcmp(snapshot, "running") == 0 || 23671f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_CURRENT) == 23681f6eb021SLiane Praza SCF_PG_TMPL_FLAG_CURRENT) { 23691f6eb021SLiane Praza if (_get_snapshot(inst, NULL, &snap) == -1) 23701f6eb021SLiane Praza goto fail_non_populated; 23711f6eb021SLiane Praza } else { 23721f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 23731f6eb021SLiane Praza if (_get_snapshot(inst, snapshot, 23741f6eb021SLiane Praza &snap) == -1) { 23751f6eb021SLiane Praza goto fail_non_populated; 23761f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 23771f6eb021SLiane Praza goto fail_non_populated; 23781f6eb021SLiane Praza } 23791f6eb021SLiane Praza } 23801f6eb021SLiane Praza } else { 23811f6eb021SLiane Praza scf_snapshot_destroy(snap); 23821f6eb021SLiane Praza snap = NULL; 23831f6eb021SLiane Praza } 23841f6eb021SLiane Praza 23851f6eb021SLiane Praza pg_tmpl = t; 23861f6eb021SLiane Praza pg_tmpl->pt_orig_inst = inst; 23871f6eb021SLiane Praza pg_tmpl->pt_orig_svc = svc; 23881f6eb021SLiane Praza pg_tmpl->pt_snap = snap; 23891f6eb021SLiane Praza pg_tmpl->pt_is_iter = 1; 23901f6eb021SLiane Praza pg_tmpl->pt_iter_last = SCF__TMPL_ITER_NONE; 23911f6eb021SLiane Praza pg_tmpl->pt_pg = pg; 23921f6eb021SLiane Praza pg_tmpl->pt_populated = 1; 23931f6eb021SLiane Praza } else { 23941f6eb021SLiane Praza if (t->pt_is_iter != 1) { 23951f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 23961f6eb021SLiane Praza return (-1); 23971f6eb021SLiane Praza } 23981f6eb021SLiane Praza pg_tmpl = t; 23991f6eb021SLiane Praza assert(pg_tmpl->pt_pg != NULL); 24001f6eb021SLiane Praza } 24011f6eb021SLiane Praza 24021f6eb021SLiane Praza if (pg_tmpl->pt_iter == NULL) { 24031f6eb021SLiane Praza pg_tmpl->pt_iter = _get_next_iterator(h, pg_tmpl, snapshot, 24041f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0); 24051f6eb021SLiane Praza if (pg_tmpl->pt_iter == NULL) { 24061f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 24071f6eb021SLiane Praza return (0); 24081f6eb021SLiane Praza else 24091f6eb021SLiane Praza return (-1); 24101f6eb021SLiane Praza } 24111f6eb021SLiane Praza } 24121f6eb021SLiane Praza 24131f6eb021SLiane Praza while (found == 0) { 24141f6eb021SLiane Praza while ((err = scf_iter_next_pg(pg_tmpl->pt_iter, 24151f6eb021SLiane Praza pg_tmpl->pt_pg)) != 1) { 24161f6eb021SLiane Praza if (err == -1) { 24171f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 24181f6eb021SLiane Praza return (-1); 24191f6eb021SLiane Praza } else switch (scf_error()) { 24201f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 24211f6eb021SLiane Praza return (-1); 24221f6eb021SLiane Praza 24231f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 24241f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 24251f6eb021SLiane Praza default: 24261f6eb021SLiane Praza assert(0); 24271f6eb021SLiane Praza abort(); 24281f6eb021SLiane Praza } 24291f6eb021SLiane Praza } else if (err == 0) { 24301f6eb021SLiane Praza /* This iteration is done. Get the next one */ 24311f6eb021SLiane Praza scf_iter_destroy(pg_tmpl->pt_iter); 24321f6eb021SLiane Praza pg_tmpl->pt_iter = _get_next_iterator(h, 24331f6eb021SLiane Praza pg_tmpl, snapshot, 24341f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0); 24351f6eb021SLiane Praza if (pg_tmpl->pt_iter == NULL) { 24361f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 24371f6eb021SLiane Praza return (0); 24381f6eb021SLiane Praza else 24391f6eb021SLiane Praza return (-1); 24401f6eb021SLiane Praza } 24411f6eb021SLiane Praza continue; 24421f6eb021SLiane Praza } else { 24431f6eb021SLiane Praza assert(0); 24441f6eb021SLiane Praza abort(); 24451f6eb021SLiane Praza } 24461f6eb021SLiane Praza } 24471f6eb021SLiane Praza 24481f6eb021SLiane Praza /* 24491f6eb021SLiane Praza * Discard pgs which don't exist at the right scoping. This 24501f6eb021SLiane Praza * check also makes sure that if we're looking at, for 24511f6eb021SLiane Praza * example, svc:/system/svc/restarter:default, that we 24521f6eb021SLiane Praza * don't hand back the same property groups twice. 24531f6eb021SLiane Praza */ 24541f6eb021SLiane Praza switch (t->pt_iter_last) { 24551f6eb021SLiane Praza case SCF__TMPL_ITER_INST: 24561f6eb021SLiane Praza ret = check_target_match(pg_tmpl->pt_pg, 24571f6eb021SLiane Praza SCF_TM_TARGET_THIS); 24581f6eb021SLiane Praza break; 24591f6eb021SLiane Praza case SCF__TMPL_ITER_RESTARTER: 24601f6eb021SLiane Praza ret = check_target_match(pg_tmpl->pt_pg, 24611f6eb021SLiane Praza SCF_TM_TARGET_DELEGATE); 24621f6eb021SLiane Praza break; 24631f6eb021SLiane Praza case SCF__TMPL_ITER_GLOBAL: 24641f6eb021SLiane Praza ret = check_target_match(pg_tmpl->pt_pg, 24651f6eb021SLiane Praza SCF_TM_TARGET_ALL); 24661f6eb021SLiane Praza break; 24671f6eb021SLiane Praza case SCF__TMPL_ITER_NONE: 24681f6eb021SLiane Praza default: 24691f6eb021SLiane Praza assert(0); 24701f6eb021SLiane Praza abort(); 24711f6eb021SLiane Praza } 24721f6eb021SLiane Praza 24731f6eb021SLiane Praza if (ret != 0) 24741f6eb021SLiane Praza continue; 24751f6eb021SLiane Praza 24761f6eb021SLiane Praza /* 24771f6eb021SLiane Praza * If walking only required property groups, check if 24781f6eb021SLiane Praza * the retrieved group is required. 24791f6eb021SLiane Praza */ 24801f6eb021SLiane Praza if (flags & SCF_PG_TMPL_FLAG_REQUIRED) { 24811f6eb021SLiane Praza if (scf_tmpl_pg_required(pg_tmpl, &required) == 0) { 24821f6eb021SLiane Praza if (required == 0) 24831f6eb021SLiane Praza continue; 24841f6eb021SLiane Praza } else { 24851f6eb021SLiane Praza return (-1); 24861f6eb021SLiane Praza } 24871f6eb021SLiane Praza } 24881f6eb021SLiane Praza 24891f6eb021SLiane Praza /* 24901f6eb021SLiane Praza * If type != NULL, check if type property matches. If no 24911f6eb021SLiane Praza * type property exists, consider it a match. 24921f6eb021SLiane Praza */ 24931f6eb021SLiane Praza if (type != NULL) { 24941f6eb021SLiane Praza if (scf_tmpl_pg_type(pg_tmpl, &tmpl_type) != -1) { 24951f6eb021SLiane Praza if (strcmp(tmpl_type, SCF_TMPL_WILDCARD) 24961f6eb021SLiane Praza == 0 || strcmp(type, tmpl_type) == 0) { 24971f6eb021SLiane Praza free(tmpl_type); 24981f6eb021SLiane Praza break; 24991f6eb021SLiane Praza } 25001f6eb021SLiane Praza free(tmpl_type); 25011f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND || 25021f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED || 25031f6eb021SLiane Praza scf_error() == SCF_ERROR_TYPE_MISMATCH) { 25041f6eb021SLiane Praza break; 25051f6eb021SLiane Praza } else { 25061f6eb021SLiane Praza return (-1); 25071f6eb021SLiane Praza } 25081f6eb021SLiane Praza } else { 25091f6eb021SLiane Praza break; 25101f6eb021SLiane Praza } 25111f6eb021SLiane Praza } 25121f6eb021SLiane Praza 25131f6eb021SLiane Praza return (1); 25141f6eb021SLiane Praza 25151f6eb021SLiane Praza fail_non_populated: 25161f6eb021SLiane Praza scf_service_destroy(svc); 25171f6eb021SLiane Praza scf_instance_destroy(inst); 25181f6eb021SLiane Praza scf_pg_destroy(pg); 25191f6eb021SLiane Praza scf_snapshot_destroy(snap); 25201f6eb021SLiane Praza return (-1); 25211f6eb021SLiane Praza } 25221f6eb021SLiane Praza 25231f6eb021SLiane Praza void 25241f6eb021SLiane Praza scf_tmpl_pg_destroy(scf_pg_tmpl_t *t) 25251f6eb021SLiane Praza { 25261f6eb021SLiane Praza if (t == NULL) 25271f6eb021SLiane Praza return; 25281f6eb021SLiane Praza 25291f6eb021SLiane Praza scf_pg_destroy(t->pt_pg); 25301f6eb021SLiane Praza scf_instance_destroy(t->pt_inst); 25311f6eb021SLiane Praza if (t->pt_inst != t->pt_orig_inst) 25321f6eb021SLiane Praza scf_instance_destroy(t->pt_orig_inst); 25331f6eb021SLiane Praza scf_snapshot_destroy(t->pt_snap); 25341f6eb021SLiane Praza scf_service_destroy(t->pt_orig_svc); 25351f6eb021SLiane Praza if (t->pt_svc != t->pt_orig_svc) 25361f6eb021SLiane Praza scf_service_destroy(t->pt_svc); 25371f6eb021SLiane Praza scf_iter_destroy(t->pt_iter); 25381f6eb021SLiane Praza free(t); 25391f6eb021SLiane Praza } 25401f6eb021SLiane Praza 25411f6eb021SLiane Praza void 25421f6eb021SLiane Praza scf_tmpl_pg_reset(scf_pg_tmpl_t *t) 25431f6eb021SLiane Praza { 25441f6eb021SLiane Praza scf_pg_destroy(t->pt_pg); 25451f6eb021SLiane Praza t->pt_pg = NULL; 25461f6eb021SLiane Praza 25471f6eb021SLiane Praza scf_instance_destroy(t->pt_inst); 25481f6eb021SLiane Praza if (t->pt_inst != t->pt_orig_inst) 25491f6eb021SLiane Praza scf_instance_destroy(t->pt_orig_inst); 25501f6eb021SLiane Praza t->pt_inst = NULL; 25511f6eb021SLiane Praza t->pt_orig_inst = NULL; 25521f6eb021SLiane Praza 25531f6eb021SLiane Praza scf_snapshot_destroy(t->pt_snap); 25541f6eb021SLiane Praza t->pt_snap = NULL; 25551f6eb021SLiane Praza 25561f6eb021SLiane Praza scf_service_destroy(t->pt_orig_svc); 25571f6eb021SLiane Praza if (t->pt_svc != t->pt_orig_svc) 25581f6eb021SLiane Praza scf_service_destroy(t->pt_svc); 25591f6eb021SLiane Praza t->pt_orig_svc = NULL; 25601f6eb021SLiane Praza t->pt_svc = NULL; 25611f6eb021SLiane Praza 25621f6eb021SLiane Praza scf_iter_destroy(t->pt_iter); 25631f6eb021SLiane Praza t->pt_iter = NULL; 25641f6eb021SLiane Praza 25651f6eb021SLiane Praza t->pt_populated = 0; 25661f6eb021SLiane Praza t->pt_is_iter = 0; 25671f6eb021SLiane Praza t->pt_iter_last = 0; 25681f6eb021SLiane Praza 25691f6eb021SLiane Praza /* Do not reset t->pt_h. */ 25701f6eb021SLiane Praza } 25711f6eb021SLiane Praza 25721f6eb021SLiane Praza /* 25731f6eb021SLiane Praza * int scf_tmpl_get_by_prop() 25741f6eb021SLiane Praza * 25751f6eb021SLiane Praza * Get the property template given a property group template and property 25761f6eb021SLiane Praza * name. No flags are currently defined for this function. 25771f6eb021SLiane Praza * 25781f6eb021SLiane Praza * Returns NULL on failure, and sets scf_error(): 25791f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 25801f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 25811f6eb021SLiane Praza * SCF_ERROR_DELETED 25821f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 25831f6eb021SLiane Praza * SCF_ERROR_INTERNAL 25841f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 25851f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 25861f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 25871f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 25881f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 25891f6eb021SLiane Praza * Template object matching property doesn't exist in the repository. 25901f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 25911f6eb021SLiane Praza * Matching template object is the wrong type in the repository. 25921f6eb021SLiane Praza */ 25931f6eb021SLiane Praza int 25941f6eb021SLiane Praza scf_tmpl_get_by_prop(scf_pg_tmpl_t *t, const char *prop, 25951f6eb021SLiane Praza scf_prop_tmpl_t *prop_tmpl, int flags) 25961f6eb021SLiane Praza { 25971f6eb021SLiane Praza char *tmpl_prop_name; 25981f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 25991f6eb021SLiane Praza char *pg_type; 26001f6eb021SLiane Praza int found = 0; 26011f6eb021SLiane Praza 26021f6eb021SLiane Praza if (flags != 0) { 26031f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 26041f6eb021SLiane Praza return (-1); 26051f6eb021SLiane Praza } 26061f6eb021SLiane Praza 26071f6eb021SLiane Praza scf_tmpl_prop_reset(prop_tmpl); 26081f6eb021SLiane Praza if ((pg = scf_pg_create(scf_pg_handle(t->pt_pg))) == NULL) 26091f6eb021SLiane Praza return (-1); 26101f6eb021SLiane Praza 26111f6eb021SLiane Praza tmpl_prop_name = _tmpl_prop_name(prop, t); 26121f6eb021SLiane Praza if (tmpl_prop_name == NULL) { 26131f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 26141f6eb021SLiane Praza return (-1); 26151f6eb021SLiane Praza } 26161f6eb021SLiane Praza 26171f6eb021SLiane Praza if (_get_pg(t->pt_svc, t->pt_inst, t->pt_snap, 26181f6eb021SLiane Praza tmpl_prop_name, pg) != 0) { 26191f6eb021SLiane Praza if (!ismember(scf_error(), errors_server)) { 26201f6eb021SLiane Praza switch (scf_error()) { 26211f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 26221f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 26231f6eb021SLiane Praza break; 26241f6eb021SLiane Praza 26251f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 26261f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 26271f6eb021SLiane Praza default: 26281f6eb021SLiane Praza assert(0); 26291f6eb021SLiane Praza abort(); 26301f6eb021SLiane Praza } 26311f6eb021SLiane Praza } 26321f6eb021SLiane Praza } else { 26331f6eb021SLiane Praza /* 26341f6eb021SLiane Praza * We've only found a template property group if the type 26351f6eb021SLiane Praza * is correct. 26361f6eb021SLiane Praza */ 26371f6eb021SLiane Praza if ((pg_type = _scf_get_pg_type(pg)) != NULL && 26381f6eb021SLiane Praza strcmp(pg_type, SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0) 26391f6eb021SLiane Praza found++; 26401f6eb021SLiane Praza else 26411f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TYPE_MISMATCH); 26421f6eb021SLiane Praza 26431f6eb021SLiane Praza 26441f6eb021SLiane Praza free(pg_type); 26451f6eb021SLiane Praza } 26461f6eb021SLiane Praza 26471f6eb021SLiane Praza if (found == 0) { 26481f6eb021SLiane Praza scf_pg_destroy(pg); 26491f6eb021SLiane Praza free(tmpl_prop_name); 26501f6eb021SLiane Praza return (-1); 26511f6eb021SLiane Praza } 26521f6eb021SLiane Praza 26531f6eb021SLiane Praza prop_tmpl->prt_h = scf_pg_handle(t->pt_pg); 26541f6eb021SLiane Praza prop_tmpl->prt_t = t; 26551f6eb021SLiane Praza prop_tmpl->prt_pg = pg; 26561f6eb021SLiane Praza prop_tmpl->prt_pg_name = tmpl_prop_name; 26571f6eb021SLiane Praza prop_tmpl->prt_populated = 1; 26581f6eb021SLiane Praza 26591f6eb021SLiane Praza return (0); 26601f6eb021SLiane Praza } 26611f6eb021SLiane Praza 26621f6eb021SLiane Praza /* 26631f6eb021SLiane Praza * scf_prop_tmpl_t *scf_tmpl_prop_create(scf_handle_t *); 26641f6eb021SLiane Praza * 26651f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT, or 26661f6eb021SLiane Praza * _NO_MEMORY. 26671f6eb021SLiane Praza */ 26681f6eb021SLiane Praza scf_prop_tmpl_t * 26691f6eb021SLiane Praza scf_tmpl_prop_create(scf_handle_t *handle) 26701f6eb021SLiane Praza { 26711f6eb021SLiane Praza scf_prop_tmpl_t *pt; 26721f6eb021SLiane Praza 26731f6eb021SLiane Praza if (handle == NULL) { 26741f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 26751f6eb021SLiane Praza return (NULL); 26761f6eb021SLiane Praza } 26771f6eb021SLiane Praza pt = calloc(1, sizeof (scf_prop_tmpl_t)); 26781f6eb021SLiane Praza if (pt == NULL) 26791f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 26801f6eb021SLiane Praza else 26811f6eb021SLiane Praza pt->prt_h = handle; 26821f6eb021SLiane Praza 26831f6eb021SLiane Praza return (pt); 26841f6eb021SLiane Praza } 26851f6eb021SLiane Praza 26861f6eb021SLiane Praza /* 26871f6eb021SLiane Praza * int scf_tmpl_iter_props() 26881f6eb021SLiane Praza * 26891f6eb021SLiane Praza * Iterates over all property templates defined in the specified property 26901f6eb021SLiane Praza * group template. The iterator state is stored on the property template 26911f6eb021SLiane Praza * data structure, and the data structure should be allocated with 26921f6eb021SLiane Praza * scf_tmpl_prop_create(). To continue the iteration, the previously 26931f6eb021SLiane Praza * returned structure should be passed in as an argument to this function. 26941f6eb021SLiane Praza * flags can include SCF_PROP_TMPL_FLAG_REQUIRED. The function returns 26951f6eb021SLiane Praza * 1 when a result was found, and 0 when the iteration is complete. 26961f6eb021SLiane Praza * 26971f6eb021SLiane Praza * Returns -1 on failure, and sets scf_error(): 26981f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 26991f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 27001f6eb021SLiane Praza * SCF_ERROR_DELETED 27011f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 27021f6eb021SLiane Praza * SCF_ERROR_INTERNAL 27031f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 27041f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 27051f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 27061f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 27071f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 27081f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 27091f6eb021SLiane Praza * Template data is invalid. One of the property templates in this 27101f6eb021SLiane Praza * pg_tmpl is malformed. 27111f6eb021SLiane Praza */ 27121f6eb021SLiane Praza int 27131f6eb021SLiane Praza scf_tmpl_iter_props(scf_pg_tmpl_t *t, scf_prop_tmpl_t *pt, int flags) 27141f6eb021SLiane Praza { 27151f6eb021SLiane Praza scf_prop_tmpl_t *prop_tmpl; 27161f6eb021SLiane Praza char *pg_pat; 27171f6eb021SLiane Praza char *pg_name = NULL; 27181f6eb021SLiane Praza int err; 27191f6eb021SLiane Praza int ret; 27201f6eb021SLiane Praza ssize_t size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 27211f6eb021SLiane Praza uint8_t required; 27221f6eb021SLiane Praza scf_handle_t *h; 27231f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 27241f6eb021SLiane Praza scf_iter_t *iter = NULL; 27251f6eb021SLiane Praza 27261f6eb021SLiane Praza assert(size != 0); 27271f6eb021SLiane Praza if (t == NULL || pt == NULL) { 27281f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 27291f6eb021SLiane Praza return (-1); 27301f6eb021SLiane Praza } 27311f6eb021SLiane Praza 27321f6eb021SLiane Praza assert(t->pt_inst == NULL || t->pt_svc == NULL); 27331f6eb021SLiane Praza assert(t->pt_inst != NULL || t->pt_svc != NULL); 27341f6eb021SLiane Praza 27351f6eb021SLiane Praza if ((pg_name = malloc(size)) == NULL) { 27361f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 27371f6eb021SLiane Praza return (-1); 27381f6eb021SLiane Praza } 27391f6eb021SLiane Praza 27401f6eb021SLiane Praza if (pt->prt_populated == 0) { 27411f6eb021SLiane Praza if ((h = scf_pg_handle(t->pt_pg)) == NULL) 27421f6eb021SLiane Praza goto fail_non_populated; 27431f6eb021SLiane Praza 27441f6eb021SLiane Praza if ((pg = scf_pg_create(h)) == NULL || 27451f6eb021SLiane Praza (iter = scf_iter_create(h)) == NULL) 27461f6eb021SLiane Praza goto fail_non_populated; 27471f6eb021SLiane Praza 27481f6eb021SLiane Praza if (t->pt_inst != NULL) 27491f6eb021SLiane Praza err = scf_iter_instance_pgs_typed_composed(iter, 27501f6eb021SLiane Praza t->pt_inst, t->pt_snap, 27511f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PROP_PATTERN); 27521f6eb021SLiane Praza else if (t->pt_svc != NULL) 27531f6eb021SLiane Praza err = scf_iter_service_pgs_typed(iter, t->pt_svc, 27541f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PROP_PATTERN); 27551f6eb021SLiane Praza 27561f6eb021SLiane Praza if (err != 0) { 27571f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 27581f6eb021SLiane Praza goto fail_non_populated; 27591f6eb021SLiane Praza } else switch (scf_error()) { 27601f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 27611f6eb021SLiane Praza goto fail_non_populated; 27621f6eb021SLiane Praza 27631f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 27641f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 27651f6eb021SLiane Praza default: 27661f6eb021SLiane Praza assert(0); 27671f6eb021SLiane Praza abort(); 27681f6eb021SLiane Praza } 27691f6eb021SLiane Praza 27701f6eb021SLiane Praza } 27711f6eb021SLiane Praza prop_tmpl = pt; 27721f6eb021SLiane Praza prop_tmpl->prt_t = t; 27731f6eb021SLiane Praza prop_tmpl->prt_populated = 1; 27741f6eb021SLiane Praza prop_tmpl->prt_pg = pg; 27751f6eb021SLiane Praza prop_tmpl->prt_iter = iter; 27761f6eb021SLiane Praza } else { 27771f6eb021SLiane Praza prop_tmpl = pt; 27781f6eb021SLiane Praza } 27791f6eb021SLiane Praza 27801f6eb021SLiane Praza while ((err = scf_iter_next_pg(prop_tmpl->prt_iter, 27811f6eb021SLiane Praza prop_tmpl->prt_pg)) > 0) { 27821f6eb021SLiane Praza /* 27831f6eb021SLiane Praza * Check if the name matches the appropriate property 27841f6eb021SLiane Praza * group template name. 27851f6eb021SLiane Praza */ 27861f6eb021SLiane Praza pg_pat = _scf_read_single_astring_from_pg(prop_tmpl->prt_pg, 27871f6eb021SLiane Praza SCF_PROPERTY_TM_PG_PATTERN); 27881f6eb021SLiane Praza if (pg_pat == NULL) { 27891f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 27901f6eb021SLiane Praza uu_free(pg_name); 27911f6eb021SLiane Praza return (-1); 27921f6eb021SLiane Praza } else switch (scf_error()) { 27931f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 27941f6eb021SLiane Praza continue; 27951f6eb021SLiane Praza 27961f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 27971f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 27981f6eb021SLiane Praza (void) scf_set_error( 27991f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 28001f6eb021SLiane Praza free(pg_name); 28011f6eb021SLiane Praza return (-1); 28021f6eb021SLiane Praza 28031f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 28041f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 28051f6eb021SLiane Praza default: 28061f6eb021SLiane Praza assert(0); 28071f6eb021SLiane Praza abort(); 28081f6eb021SLiane Praza } 28091f6eb021SLiane Praza } 28101f6eb021SLiane Praza if ((ret = scf_pg_get_name(t->pt_pg, pg_name, size)) <= 0) { 28111f6eb021SLiane Praza free(pg_pat); 28121f6eb021SLiane Praza if (ret == 0) 28131f6eb021SLiane Praza continue; 28141f6eb021SLiane Praza 28151f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 28161f6eb021SLiane Praza free(pg_name); 28171f6eb021SLiane Praza return (-1); 28181f6eb021SLiane Praza } else { 28191f6eb021SLiane Praza assert(0); 28201f6eb021SLiane Praza abort(); 28211f6eb021SLiane Praza } 28221f6eb021SLiane Praza } 28231f6eb021SLiane Praza if (strcmp(pg_pat, pg_name) != 0) { 28241f6eb021SLiane Praza free(pg_pat); 28251f6eb021SLiane Praza continue; 28261f6eb021SLiane Praza } 28271f6eb021SLiane Praza free(pg_pat); 28281f6eb021SLiane Praza 28291f6eb021SLiane Praza /* 28301f6eb021SLiane Praza * If walking only required properties, check if 28311f6eb021SLiane Praza * the retrieved property is required. 28321f6eb021SLiane Praza */ 28331f6eb021SLiane Praza if (flags & SCF_PROP_TMPL_FLAG_REQUIRED) { 28341f6eb021SLiane Praza if (scf_tmpl_prop_required(prop_tmpl, &required) == 0) { 28351f6eb021SLiane Praza if (required == 0) 28361f6eb021SLiane Praza continue; 28371f6eb021SLiane Praza } else { 28381f6eb021SLiane Praza free(pg_name); 28391f6eb021SLiane Praza return (-1); 28401f6eb021SLiane Praza } 28411f6eb021SLiane Praza } 28421f6eb021SLiane Praza free(pg_name); 28431f6eb021SLiane Praza return (0); 28441f6eb021SLiane Praza } 28451f6eb021SLiane Praza 28461f6eb021SLiane Praza if (err == -1) { 28471f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 28481f6eb021SLiane Praza free(pg_name); 28491f6eb021SLiane Praza return (-1); 28501f6eb021SLiane Praza } else { 28511f6eb021SLiane Praza assert(0); 28521f6eb021SLiane Praza abort(); 28531f6eb021SLiane Praza } 28541f6eb021SLiane Praza } else if (err == 0) { 28551f6eb021SLiane Praza scf_iter_destroy(prop_tmpl->prt_iter); 28561f6eb021SLiane Praza prop_tmpl->prt_iter = NULL; 28571f6eb021SLiane Praza prop_tmpl->prt_populated = 0; 28581f6eb021SLiane Praza } 28591f6eb021SLiane Praza free(pg_name); 28601f6eb021SLiane Praza 28611f6eb021SLiane Praza return (1); 28621f6eb021SLiane Praza 28631f6eb021SLiane Praza fail_non_populated: 28641f6eb021SLiane Praza free(pg_name); 28651f6eb021SLiane Praza scf_pg_destroy(pg); 28661f6eb021SLiane Praza scf_iter_destroy(iter); 28671f6eb021SLiane Praza return (-1); 28681f6eb021SLiane Praza } 28691f6eb021SLiane Praza 28701f6eb021SLiane Praza void 28711f6eb021SLiane Praza scf_tmpl_prop_destroy(scf_prop_tmpl_t *t) 28721f6eb021SLiane Praza { 28731f6eb021SLiane Praza if (t == NULL) 28741f6eb021SLiane Praza return; 28751f6eb021SLiane Praza 28761f6eb021SLiane Praza scf_pg_destroy(t->prt_pg); 28771f6eb021SLiane Praza free(t->prt_pg_name); 28781f6eb021SLiane Praza free(t->prt_iter); 28791f6eb021SLiane Praza free(t); 28801f6eb021SLiane Praza } 28811f6eb021SLiane Praza 28821f6eb021SLiane Praza void 28831f6eb021SLiane Praza scf_tmpl_prop_reset(scf_prop_tmpl_t *t) 28841f6eb021SLiane Praza { 28851f6eb021SLiane Praza scf_pg_destroy(t->prt_pg); 28861f6eb021SLiane Praza t->prt_pg = NULL; 28871f6eb021SLiane Praza 28881f6eb021SLiane Praza free(t->prt_pg_name); 28891f6eb021SLiane Praza t->prt_pg_name = NULL; 28901f6eb021SLiane Praza 28911f6eb021SLiane Praza free(t->prt_iter); 28921f6eb021SLiane Praza t->prt_iter = NULL; 28931f6eb021SLiane Praza 28941f6eb021SLiane Praza t->prt_populated = 0; 28951f6eb021SLiane Praza t->prt_h = NULL; 28961f6eb021SLiane Praza t->prt_t = NULL; 28971f6eb021SLiane Praza } 28981f6eb021SLiane Praza 28991f6eb021SLiane Praza /* 29001f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 29011f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 29021f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 29031f6eb021SLiane Praza * SCF_ERROR_DELETED 29041f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 29051f6eb021SLiane Praza * SCF_ERROR_INTERNAL 29061f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 29071f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 29081f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 29091f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 29101f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 29111f6eb021SLiane Praza * The name of the template property group (the pname property) has 29121f6eb021SLiane Praza * an improper repository format and is not type astring or has 29131f6eb021SLiane Praza * more than one value. 29141f6eb021SLiane Praza */ 29151f6eb021SLiane Praza ssize_t 29161f6eb021SLiane Praza scf_tmpl_pg_name(const scf_pg_tmpl_t *t, char **out) 29171f6eb021SLiane Praza { 29181f6eb021SLiane Praza return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_NAME, out)); 29191f6eb021SLiane Praza } 29201f6eb021SLiane Praza 29211f6eb021SLiane Praza /* 29221f6eb021SLiane Praza * returns an allocated string that must be freed 29231f6eb021SLiane Praza * 29241f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 29251f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 29261f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 29271f6eb021SLiane Praza * SCF_ERROR_DELETED 29281f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 29291f6eb021SLiane Praza * SCF_ERROR_INTERNAL 29301f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 29311f6eb021SLiane Praza * name not a valid property name 29321f6eb021SLiane Praza * name and locale are too long to make a property name 29331f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 29341f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 29351f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 29361f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 29371f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 29381f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 29391f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 29401f6eb021SLiane Praza */ 29411f6eb021SLiane Praza static char * 29421f6eb021SLiane Praza _read_localized_astring_from_pg(scf_propertygroup_t *pg, const char *name, 29431f6eb021SLiane Praza const char *locale) 29441f6eb021SLiane Praza { 29451f6eb021SLiane Praza char *str; 29461f6eb021SLiane Praza char *lname_prop; 29471f6eb021SLiane Praza 29481f6eb021SLiane Praza str = _add_locale_to_name(name, locale); 29491f6eb021SLiane Praza if (str == NULL) 29501f6eb021SLiane Praza return (NULL); 29511f6eb021SLiane Praza lname_prop = _scf_read_single_astring_from_pg(pg, str); 29521f6eb021SLiane Praza if (lname_prop == NULL) { 29531f6eb021SLiane Praza free(str); 29541f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) 29551f6eb021SLiane Praza return (NULL); 29561f6eb021SLiane Praza str = _add_locale_to_name(name, "C"); 29571f6eb021SLiane Praza if (str == NULL) 29581f6eb021SLiane Praza return (NULL); 29591f6eb021SLiane Praza lname_prop = _scf_read_single_astring_from_pg(pg, str); 29601f6eb021SLiane Praza } 29611f6eb021SLiane Praza free(str); 29621f6eb021SLiane Praza if (lname_prop == NULL) { 29631f6eb021SLiane Praza if (scf_error() == SCF_ERROR_TYPE_MISMATCH || 29641f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) 29651f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 29661f6eb021SLiane Praza } 29671f6eb021SLiane Praza return (lname_prop); 29681f6eb021SLiane Praza } 29691f6eb021SLiane Praza 29701f6eb021SLiane Praza /* 29711f6eb021SLiane Praza * returns an allocated string that must be freed 29721f6eb021SLiane Praza * 29731f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 29741f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 29751f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 29761f6eb021SLiane Praza * SCF_ERROR_DELETED 29771f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 29781f6eb021SLiane Praza * SCF_ERROR_INTERNAL 29791f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 29801f6eb021SLiane Praza * locale is too long to make a valid property name 29811f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 29821f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 29831f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 29841f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 29851f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 29861f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 29871f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 29881f6eb021SLiane Praza */ 29891f6eb021SLiane Praza ssize_t 29901f6eb021SLiane Praza scf_tmpl_pg_common_name(const scf_pg_tmpl_t *t, const char *locale, char **out) 29911f6eb021SLiane Praza { 29921f6eb021SLiane Praza assert(out != NULL); 29931f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->pt_pg, 29941f6eb021SLiane Praza SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL) 29951f6eb021SLiane Praza return (-1); 29961f6eb021SLiane Praza 29971f6eb021SLiane Praza return (strlen(*out)); 29981f6eb021SLiane Praza } 29991f6eb021SLiane Praza 30001f6eb021SLiane Praza /* 30011f6eb021SLiane Praza * returns an allocated string that must be freed 30021f6eb021SLiane Praza * 30031f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 30041f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 30051f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 30061f6eb021SLiane Praza * SCF_ERROR_DELETED 30071f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 30081f6eb021SLiane Praza * SCF_ERROR_INTERNAL 30091f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 30101f6eb021SLiane Praza * locale is too long to make a valid property name 30111f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 30121f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 30131f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 30141f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 30151f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 30161f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 30171f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 30181f6eb021SLiane Praza */ 30191f6eb021SLiane Praza ssize_t 30201f6eb021SLiane Praza scf_tmpl_pg_description(const scf_pg_tmpl_t *t, const char *locale, char **out) 30211f6eb021SLiane Praza { 30221f6eb021SLiane Praza assert(out != NULL); 30231f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->pt_pg, 30241f6eb021SLiane Praza SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL) 30251f6eb021SLiane Praza return (-1); 30261f6eb021SLiane Praza 30271f6eb021SLiane Praza return (strlen(*out)); 30281f6eb021SLiane Praza } 30291f6eb021SLiane Praza 30301f6eb021SLiane Praza /* 30311f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 30321f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 30331f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 30341f6eb021SLiane Praza * SCF_ERROR_DELETED 30351f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 30361f6eb021SLiane Praza * SCF_ERROR_INTERNAL 30371f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 30381f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 30391f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 30401f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 30411f6eb021SLiane Praza * 'type' property doesn't exist or exists and has no value. 30421f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 30431f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 30441f6eb021SLiane Praza * 'type' property is not SCF_TYPE_ASTRING or has more than one value. 30451f6eb021SLiane Praza */ 30461f6eb021SLiane Praza ssize_t 30471f6eb021SLiane Praza scf_tmpl_pg_type(const scf_pg_tmpl_t *t, char **out) 30481f6eb021SLiane Praza { 30491f6eb021SLiane Praza return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_TYPE, out)); 30501f6eb021SLiane Praza } 30511f6eb021SLiane Praza 30521f6eb021SLiane Praza /* 30531f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 30541f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 30551f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 30561f6eb021SLiane Praza * SCF_ERROR_DELETED 30571f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 30581f6eb021SLiane Praza * SCF_ERROR_INTERNAL 30591f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 30601f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 30611f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 30621f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 30631f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 30641f6eb021SLiane Praza * required property is not SCF_TYPE_BOOLEAN or has more than one value. 30651f6eb021SLiane Praza */ 30661f6eb021SLiane Praza int 30671f6eb021SLiane Praza scf_tmpl_pg_required(const scf_pg_tmpl_t *t, uint8_t *out) 30681f6eb021SLiane Praza { 30691f6eb021SLiane Praza 30701f6eb021SLiane Praza if (_read_single_boolean_from_pg(t->pt_pg, SCF_PROPERTY_TM_REQUIRED, 30711f6eb021SLiane Praza out) == -1) { 30721f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 30731f6eb021SLiane Praza return (-1); 30741f6eb021SLiane Praza } else switch (scf_error()) { 30751f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 30761f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 30771f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 30781f6eb021SLiane Praza return (-1); 30791f6eb021SLiane Praza 30801f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 30811f6eb021SLiane Praza *out = 0; 30821f6eb021SLiane Praza return (0); 30831f6eb021SLiane Praza 30841f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 30851f6eb021SLiane Praza default: 30861f6eb021SLiane Praza assert(0); 30871f6eb021SLiane Praza abort(); 30881f6eb021SLiane Praza } 30891f6eb021SLiane Praza } 30901f6eb021SLiane Praza 30911f6eb021SLiane Praza return (0); 30921f6eb021SLiane Praza } 30931f6eb021SLiane Praza 30941f6eb021SLiane Praza /* 30951f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 30961f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 30971f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 30981f6eb021SLiane Praza * SCF_ERROR_DELETED 30991f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 31001f6eb021SLiane Praza * SCF_ERROR_INTERNAL 31011f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 31021f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 31031f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 31041f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 31051f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 31061f6eb021SLiane Praza * target property is not SCF_TYPE_ASTRING or has more than one value. 31071f6eb021SLiane Praza */ 31081f6eb021SLiane Praza ssize_t 31091f6eb021SLiane Praza scf_tmpl_pg_target(const scf_pg_tmpl_t *t, char **out) 31101f6eb021SLiane Praza { 31111f6eb021SLiane Praza *out = _scf_read_single_astring_from_pg(t->pt_pg, 31121f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 31131f6eb021SLiane Praza 31141f6eb021SLiane Praza if (*out == NULL) { 31151f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 31161f6eb021SLiane Praza return (-1); 31171f6eb021SLiane Praza } else switch (scf_error()) { 31181f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 31191f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 31201f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 31211f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 31221f6eb021SLiane Praza return (-1); 31231f6eb021SLiane Praza 31241f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 31251f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 31261f6eb021SLiane Praza default: 31271f6eb021SLiane Praza assert(0); 31281f6eb021SLiane Praza abort(); 31291f6eb021SLiane Praza } 31301f6eb021SLiane Praza } 31311f6eb021SLiane Praza 31321f6eb021SLiane Praza return (strlen(*out)); 31331f6eb021SLiane Praza } 31341f6eb021SLiane Praza 31351f6eb021SLiane Praza /* 31361f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 31371f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 31381f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 31391f6eb021SLiane Praza * SCF_ERROR_DELETED 31401f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 31411f6eb021SLiane Praza * SCF_ERROR_INTERNAL 31421f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 31431f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 31441f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 31451f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 31461f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 31471f6eb021SLiane Praza */ 31481f6eb021SLiane Praza ssize_t 31491f6eb021SLiane Praza scf_tmpl_prop_name(const scf_prop_tmpl_t *t, char **out) 31501f6eb021SLiane Praza { 31511f6eb021SLiane Praza *out = _scf_read_single_astring_from_pg(t->prt_pg, 31521f6eb021SLiane Praza SCF_PROPERTY_TM_NAME); 31531f6eb021SLiane Praza 31541f6eb021SLiane Praza if (*out != NULL && *out[0] == '\0') { 31551f6eb021SLiane Praza free(*out); 31561f6eb021SLiane Praza *out = NULL; 31571f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 31581f6eb021SLiane Praza } 31591f6eb021SLiane Praza if (*out == NULL) { 31601f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 31611f6eb021SLiane Praza return (-1); 31621f6eb021SLiane Praza } else switch (scf_error()) { 31631f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 31641f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 31651f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 31661f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 31671f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 31681f6eb021SLiane Praza return (-1); 31691f6eb021SLiane Praza 31701f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 31711f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 31721f6eb021SLiane Praza default: 31731f6eb021SLiane Praza assert(0); 31741f6eb021SLiane Praza abort(); 31751f6eb021SLiane Praza } 31761f6eb021SLiane Praza } 31771f6eb021SLiane Praza 31781f6eb021SLiane Praza return (strlen(*out)); 31791f6eb021SLiane Praza } 31801f6eb021SLiane Praza 31811f6eb021SLiane Praza /* 31821f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 31831f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 31841f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 31851f6eb021SLiane Praza * SCF_ERROR_DELETED 31861f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 31871f6eb021SLiane Praza * SCF_ERROR_INTERNAL 31881f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 31891f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 31901f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 31911f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 31921f6eb021SLiane Praza * 'type' property doesn't exist or exists and has no value. 31931f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 31941f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 31951f6eb021SLiane Praza * 'type' property is not SCF_TYPE_ASTRING, has more than one value, 31961f6eb021SLiane Praza * is SCF_TYPE_INVALID, or is the empty string. 31971f6eb021SLiane Praza */ 31981f6eb021SLiane Praza int 31991f6eb021SLiane Praza scf_tmpl_prop_type(const scf_prop_tmpl_t *t, scf_type_t *out) 32001f6eb021SLiane Praza { 32011f6eb021SLiane Praza char *type; 32021f6eb021SLiane Praza 32031f6eb021SLiane Praza type = _scf_read_single_astring_from_pg(t->prt_pg, 32041f6eb021SLiane Praza SCF_PROPERTY_TM_TYPE); 32051f6eb021SLiane Praza if (type != NULL && type[0] == '\0') { 32061f6eb021SLiane Praza free(type); 32071f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 32081f6eb021SLiane Praza return (-1); 32091f6eb021SLiane Praza } 32101f6eb021SLiane Praza if (type == NULL) { 32111f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 32121f6eb021SLiane Praza return (-1); 32131f6eb021SLiane Praza } else switch (scf_error()) { 32141f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 32151f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 32161f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 32171f6eb021SLiane Praza /*FALLTHROUGH*/ 32181f6eb021SLiane Praza 32191f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 32201f6eb021SLiane Praza return (-1); 32211f6eb021SLiane Praza 32221f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 32231f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 32241f6eb021SLiane Praza default: 32251f6eb021SLiane Praza assert(0); 32261f6eb021SLiane Praza abort(); 32271f6eb021SLiane Praza } 32281f6eb021SLiane Praza } 32291f6eb021SLiane Praza 32301f6eb021SLiane Praza *out = scf_string_to_type(type); 32311f6eb021SLiane Praza free(type); 32321f6eb021SLiane Praza 32331f6eb021SLiane Praza if (*out == SCF_TYPE_INVALID) { 32341f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 32351f6eb021SLiane Praza return (-1); 32361f6eb021SLiane Praza } 32371f6eb021SLiane Praza 32381f6eb021SLiane Praza return (0); 32391f6eb021SLiane Praza } 32401f6eb021SLiane Praza 32411f6eb021SLiane Praza /* 32421f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 32431f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 32441f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 32451f6eb021SLiane Praza * SCF_ERROR_DELETED 32461f6eb021SLiane Praza * Property group which represents t was deleted. 32471f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 32481f6eb021SLiane Praza * SCF_ERROR_INTERNAL 32491f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 32501f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 32511f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 32521f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 32531f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 32541f6eb021SLiane Praza * required property is not SCF_TYPE_ASTRING has more than one value. 32551f6eb021SLiane Praza */ 32561f6eb021SLiane Praza int 32571f6eb021SLiane Praza scf_tmpl_prop_required(const scf_prop_tmpl_t *t, uint8_t *out) 32581f6eb021SLiane Praza { 32591f6eb021SLiane Praza if (_read_single_boolean_from_pg(t->prt_pg, SCF_PROPERTY_TM_REQUIRED, 32601f6eb021SLiane Praza out) == -1) { 32611f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 32621f6eb021SLiane Praza return (-1); 32631f6eb021SLiane Praza } else switch (scf_error()) { 32641f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 32651f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 32661f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 32671f6eb021SLiane Praza return (-1); 32681f6eb021SLiane Praza 32691f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 32701f6eb021SLiane Praza *out = 0; 32711f6eb021SLiane Praza return (0); 32721f6eb021SLiane Praza 32731f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 32741f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 32751f6eb021SLiane Praza default: 32761f6eb021SLiane Praza assert(0); 32771f6eb021SLiane Praza abort(); 32781f6eb021SLiane Praza } 32791f6eb021SLiane Praza } 32801f6eb021SLiane Praza 32811f6eb021SLiane Praza return (0); 32821f6eb021SLiane Praza } 32831f6eb021SLiane Praza 32841f6eb021SLiane Praza /* 32851f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 32861f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 32871f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 32881f6eb021SLiane Praza * SCF_ERROR_DELETED 32891f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 32901f6eb021SLiane Praza * SCF_ERROR_INTERNAL 32911f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 32921f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 32931f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 32941f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 32951f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 32961f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 32971f6eb021SLiane Praza * locale is too long to make a property name 32981f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 32991f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 33001f6eb021SLiane Praza * common_name property is not SCF_TYPE_ASTRING has more than one value. 33011f6eb021SLiane Praza */ 33021f6eb021SLiane Praza ssize_t 33031f6eb021SLiane Praza scf_tmpl_prop_common_name(const scf_prop_tmpl_t *t, const char *locale, 33041f6eb021SLiane Praza char **out) 33051f6eb021SLiane Praza { 33061f6eb021SLiane Praza assert(out != NULL); 33071f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->prt_pg, 33081f6eb021SLiane Praza SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL) 33091f6eb021SLiane Praza return (-1); 33101f6eb021SLiane Praza 33111f6eb021SLiane Praza return (strlen(*out)); 33121f6eb021SLiane Praza } 33131f6eb021SLiane Praza 33141f6eb021SLiane Praza /* 33151f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 33161f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 33171f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 33181f6eb021SLiane Praza * SCF_ERROR_DELETED 33191f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 33201f6eb021SLiane Praza * SCF_ERROR_INTERNAL 33211f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 33221f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 33231f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 33241f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 33251f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 33261f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 33271f6eb021SLiane Praza * locale is too long to make a property name 33281f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 33291f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 33301f6eb021SLiane Praza * description property is not SCF_TYPE_ASTRING has more than one value. 33311f6eb021SLiane Praza */ 33321f6eb021SLiane Praza ssize_t 33331f6eb021SLiane Praza scf_tmpl_prop_description(const scf_prop_tmpl_t *t, const char *locale, 33341f6eb021SLiane Praza char **out) 33351f6eb021SLiane Praza { 33361f6eb021SLiane Praza assert(out != NULL); 33371f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->prt_pg, 33381f6eb021SLiane Praza SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL) 33391f6eb021SLiane Praza return (-1); 33401f6eb021SLiane Praza 33411f6eb021SLiane Praza return (strlen(*out)); 33421f6eb021SLiane Praza } 33431f6eb021SLiane Praza 33441f6eb021SLiane Praza /* 33451f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 33461f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 33471f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 33481f6eb021SLiane Praza * SCF_ERROR_DELETED 33491f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 33501f6eb021SLiane Praza * SCF_ERROR_INTERNAL 33511f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 33521f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 33531f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 33541f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 33551f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 33561f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 33571f6eb021SLiane Praza * locale is too long to make a property name 33581f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 33591f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 33601f6eb021SLiane Praza * units property is not SCF_TYPE_ASTRING has more than one value. 33611f6eb021SLiane Praza */ 33621f6eb021SLiane Praza ssize_t 33631f6eb021SLiane Praza scf_tmpl_prop_units(const scf_prop_tmpl_t *t, const char *locale, char **out) 33641f6eb021SLiane Praza { 33651f6eb021SLiane Praza assert(out != NULL); 33661f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->prt_pg, 33671f6eb021SLiane Praza SCF_PROPERTY_TM_UNITS_PREFIX, locale)) == NULL) 33681f6eb021SLiane Praza return (-1); 33691f6eb021SLiane Praza 33701f6eb021SLiane Praza return (strlen(*out)); 33711f6eb021SLiane Praza } 33721f6eb021SLiane Praza 33731f6eb021SLiane Praza /* 33741f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 33751f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 33761f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 33771f6eb021SLiane Praza * SCF_ERROR_DELETED 33781f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 33791f6eb021SLiane Praza * SCF_ERROR_INTERNAL 33801f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 33811f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 33821f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 33831f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 33841f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 33851f6eb021SLiane Praza * visibility property is not SCF_TYPE_ASTRING has more than one value. 33861f6eb021SLiane Praza */ 33871f6eb021SLiane Praza int 33881f6eb021SLiane Praza scf_tmpl_prop_visibility(const scf_prop_tmpl_t *t, uint8_t *out) 33891f6eb021SLiane Praza { 33901f6eb021SLiane Praza char *visibility; 33911f6eb021SLiane Praza 33921f6eb021SLiane Praza visibility = _scf_read_single_astring_from_pg(t->prt_pg, 33931f6eb021SLiane Praza SCF_PROPERTY_TM_VISIBILITY); 33941f6eb021SLiane Praza if (visibility == NULL) { 33951f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 33961f6eb021SLiane Praza return (-1); 33971f6eb021SLiane Praza } else switch (scf_error()) { 33981f6eb021SLiane Praza /* prop doesn't exist we take the default value */ 33991f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 34001f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_READWRITE; 34011f6eb021SLiane Praza return (0); 34021f6eb021SLiane Praza 34031f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 34041f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 34051f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 34061f6eb021SLiane Praza return (-1); 34071f6eb021SLiane Praza 34081f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 34091f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 34101f6eb021SLiane Praza default: 34111f6eb021SLiane Praza assert(0); 34121f6eb021SLiane Praza abort(); 34131f6eb021SLiane Praza } 34141f6eb021SLiane Praza } else if (strcmp(visibility, SCF_TM_VISIBILITY_READWRITE) == 0) { 34151f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_READWRITE; 34161f6eb021SLiane Praza } else if (strcmp(visibility, SCF_TM_VISIBILITY_HIDDEN) == 0) { 34171f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_HIDDEN; 34181f6eb021SLiane Praza } else if (strcmp(visibility, SCF_TM_VISIBILITY_READONLY) == 0) { 34191f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_READONLY; 34201f6eb021SLiane Praza } else { 34211f6eb021SLiane Praza free(visibility); 34221f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 34231f6eb021SLiane Praza return (-1); 34241f6eb021SLiane Praza } 34251f6eb021SLiane Praza 34261f6eb021SLiane Praza free(visibility); 34271f6eb021SLiane Praza return (0); 34281f6eb021SLiane Praza } 34291f6eb021SLiane Praza 34301f6eb021SLiane Praza /* 34311f6eb021SLiane Praza * Return an allocated string containing the value that must be freed 34321f6eb021SLiane Praza * with free(). 34331f6eb021SLiane Praza * 34341f6eb021SLiane Praza * On error set scf_error() _NO_MEMORY, or _NOT_SET (val has not been set 34351f6eb021SLiane Praza * to a value). 34361f6eb021SLiane Praza */ 34371f6eb021SLiane Praza static char * 34381f6eb021SLiane Praza _scf_value_get_as_string(scf_value_t *val) 34391f6eb021SLiane Praza { 34401f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 34411f6eb021SLiane Praza char *buf = malloc(sz); 34421f6eb021SLiane Praza 34431f6eb021SLiane Praza if (buf == NULL) { 34441f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 34451f6eb021SLiane Praza } else if (scf_value_get_as_string(val, buf, sz) == -1) { 34461f6eb021SLiane Praza free(buf); 34471f6eb021SLiane Praza buf = NULL; 34481f6eb021SLiane Praza } 34491f6eb021SLiane Praza 34501f6eb021SLiane Praza return (buf); 34511f6eb021SLiane Praza } 34521f6eb021SLiane Praza 34531f6eb021SLiane Praza /* 34541f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 34551f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 34561f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 34571f6eb021SLiane Praza * SCF_ERROR_DELETED 34581f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 34591f6eb021SLiane Praza * SCF_ERROR_INTERNAL 34601f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 34611f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 34621f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 34631f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 34641f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 34651f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 34661f6eb021SLiane Praza */ 34671f6eb021SLiane Praza int 34681f6eb021SLiane Praza scf_tmpl_prop_cardinality(const scf_prop_tmpl_t *t, uint64_t *min, 34691f6eb021SLiane Praza uint64_t *max) 34701f6eb021SLiane Praza { 34711f6eb021SLiane Praza scf_value_t *val_min = NULL; 34721f6eb021SLiane Praza scf_value_t *val_max = NULL; 34731f6eb021SLiane Praza int ret = 0; 34741f6eb021SLiane Praza 34751f6eb021SLiane Praza if (_read_single_value_from_pg(t->prt_pg, 34761f6eb021SLiane Praza SCF_PROPERTY_TM_CARDINALITY_MIN, &val_min) == 0) { 34771f6eb021SLiane Praza if (scf_value_get_count(val_min, min) < 0) 34781f6eb021SLiane Praza goto error; 34791f6eb021SLiane Praza } else { 34801f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 34811f6eb021SLiane Praza *min = 0; 34821f6eb021SLiane Praza else 34831f6eb021SLiane Praza goto error; 34841f6eb021SLiane Praza } 34851f6eb021SLiane Praza 34861f6eb021SLiane Praza if (_read_single_value_from_pg(t->prt_pg, 34871f6eb021SLiane Praza SCF_PROPERTY_TM_CARDINALITY_MAX, &val_max) == 0) { 34881f6eb021SLiane Praza if (scf_value_get_count(val_max, max) < 0) 34891f6eb021SLiane Praza goto error; 34901f6eb021SLiane Praza } else { 34911f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 34921f6eb021SLiane Praza *max = UINT64_MAX; 34931f6eb021SLiane Praza else 34941f6eb021SLiane Praza goto error; 34951f6eb021SLiane Praza } 34961f6eb021SLiane Praza goto cleanup; 34971f6eb021SLiane Praza 34981f6eb021SLiane Praza error: 34991f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 35001f6eb021SLiane Praza ret = -1; 35011f6eb021SLiane Praza } else switch (scf_error()) { 35021f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 35031f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 35041f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 35051f6eb021SLiane Praza /*FALLTHROUGH*/ 35061f6eb021SLiane Praza 35071f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 35081f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 35091f6eb021SLiane Praza ret = -1; 35101f6eb021SLiane Praza break; 35111f6eb021SLiane Praza 35121f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 35131f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 35141f6eb021SLiane Praza default: 35151f6eb021SLiane Praza assert(0); 35161f6eb021SLiane Praza abort(); 35171f6eb021SLiane Praza } 35181f6eb021SLiane Praza 35191f6eb021SLiane Praza cleanup: 35201f6eb021SLiane Praza scf_value_destroy(val_min); 35211f6eb021SLiane Praza scf_value_destroy(val_max); 35221f6eb021SLiane Praza 35231f6eb021SLiane Praza return (ret); 35241f6eb021SLiane Praza } 35251f6eb021SLiane Praza 35261f6eb021SLiane Praza /* 35271f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 35281f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 35291f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 35301f6eb021SLiane Praza * SCF_ERROR_DELETED 35311f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 35321f6eb021SLiane Praza * SCF_ERROR_INTERNAL 35331f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 35341f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 35351f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 35361f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 35371f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 35381f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 35391f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 35401f6eb021SLiane Praza */ 35411f6eb021SLiane Praza int 35421f6eb021SLiane Praza scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t *t, scf_values_t *vals) 35431f6eb021SLiane Praza { 35441f6eb021SLiane Praza if (_read_astrings_values(t->prt_pg, 35451f6eb021SLiane Praza SCF_PROPERTY_INTERNAL_SEPARATORS, vals) == NULL) { 35461f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 35471f6eb021SLiane Praza return (-1); 35481f6eb021SLiane Praza } else switch (scf_error()) { 35491f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 35501f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 35511f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 35521f6eb021SLiane Praza /*FALLTHROUGH*/ 35531f6eb021SLiane Praza 35541f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 35551f6eb021SLiane Praza return (-1); 35561f6eb021SLiane Praza 35571f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 35581f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 35591f6eb021SLiane Praza default: 35601f6eb021SLiane Praza assert(0); 35611f6eb021SLiane Praza abort(); 35621f6eb021SLiane Praza } 35631f6eb021SLiane Praza } else if (vals->value_count == 0) { 35641f6eb021SLiane Praza /* property has no value */ 35651f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 35661f6eb021SLiane Praza scf_values_destroy(vals); 35671f6eb021SLiane Praza return (-1); 35681f6eb021SLiane Praza } 35691f6eb021SLiane Praza 35701f6eb021SLiane Praza return (0); 35711f6eb021SLiane Praza } 35721f6eb021SLiane Praza 35731f6eb021SLiane Praza /* 35741f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 35751f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 35761f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 35771f6eb021SLiane Praza * SCF_ERROR_DELETED 35781f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 35791f6eb021SLiane Praza * SCF_ERROR_INTERNAL 35801f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 35811f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 35821f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 35831f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 35841f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 35851f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 35861f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 35871f6eb021SLiane Praza */ 35881f6eb021SLiane Praza int 35891f6eb021SLiane Praza scf_tmpl_value_name_constraints(const scf_prop_tmpl_t *t, 35901f6eb021SLiane Praza scf_values_t *vals) 35911f6eb021SLiane Praza { 35921f6eb021SLiane Praza char **ret; 35931f6eb021SLiane Praza 35941f6eb021SLiane Praza ret = _read_astrings_values(t->prt_pg, 35951f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, vals); 35961f6eb021SLiane Praza 35971f6eb021SLiane Praza if (ret == NULL) { 35981f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 35991f6eb021SLiane Praza return (-1); 36001f6eb021SLiane Praza } else switch (scf_error()) { 36011f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 36021f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 36031f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 36041f6eb021SLiane Praza /*FALLTHROUGH*/ 36051f6eb021SLiane Praza 36061f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 36071f6eb021SLiane Praza return (-1); 36081f6eb021SLiane Praza 36091f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 36101f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 36111f6eb021SLiane Praza default: 36121f6eb021SLiane Praza assert(0); 36131f6eb021SLiane Praza abort(); 36141f6eb021SLiane Praza } 36151f6eb021SLiane Praza } else if (vals->value_count == 0) { 36161f6eb021SLiane Praza /* property has no value */ 36171f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 36181f6eb021SLiane Praza scf_values_destroy(vals); 36191f6eb021SLiane Praza return (-1); 36201f6eb021SLiane Praza } 36211f6eb021SLiane Praza 36221f6eb021SLiane Praza return (0); 36231f6eb021SLiane Praza } 36241f6eb021SLiane Praza 36251f6eb021SLiane Praza /* 36261f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 36271f6eb021SLiane Praza * Caller is responsible for freeing returned pointer after use. 36281f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 36291f6eb021SLiane Praza * More tokens than the array size supplied. 36301f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 36311f6eb021SLiane Praza */ 36321f6eb021SLiane Praza static void * 36331f6eb021SLiane Praza _separate_by_separator(char *string, const char *sep, char **array, int size) 36341f6eb021SLiane Praza { 36351f6eb021SLiane Praza char *str, *token; 36361f6eb021SLiane Praza char *lasts; 36371f6eb021SLiane Praza int n = 0; 36381f6eb021SLiane Praza 36391f6eb021SLiane Praza assert(array != NULL); 36401f6eb021SLiane Praza assert(string != NULL); 36411f6eb021SLiane Praza assert(sep != NULL); 36421f6eb021SLiane Praza assert(size > 0); 36431f6eb021SLiane Praza 36441f6eb021SLiane Praza str = strdup(string); 36451f6eb021SLiane Praza if (str == NULL) { 36461f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 36471f6eb021SLiane Praza return (NULL); 36481f6eb021SLiane Praza } 36491f6eb021SLiane Praza 36501f6eb021SLiane Praza if ((array[n] = strtok_r(str, sep, &lasts)) == NULL) { 36511f6eb021SLiane Praza assert(0); 36521f6eb021SLiane Praza abort(); 36531f6eb021SLiane Praza } 36541f6eb021SLiane Praza 36551f6eb021SLiane Praza n++; 36561f6eb021SLiane Praza while ((token = strtok_r(NULL, sep, &lasts)) != NULL) { 36571f6eb021SLiane Praza if (n >= size) { 36581f6eb021SLiane Praza goto error; 36591f6eb021SLiane Praza } 36601f6eb021SLiane Praza array[n] = token; 36611f6eb021SLiane Praza n++; 36621f6eb021SLiane Praza } 36631f6eb021SLiane Praza if (n < size) { 36641f6eb021SLiane Praza goto error; 36651f6eb021SLiane Praza } 36661f6eb021SLiane Praza 36671f6eb021SLiane Praza return (str); 36681f6eb021SLiane Praza error: 36691f6eb021SLiane Praza free(str); 36701f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 36711f6eb021SLiane Praza return (NULL); 36721f6eb021SLiane Praza } 36731f6eb021SLiane Praza 36741f6eb021SLiane Praza /* 36751f6eb021SLiane Praza * check if name is among values of CHOICES_INCLUDE_VALUES 36761f6eb021SLiane Praza * return 0 if name is present, 1 name is not present, -1 on failure 36771f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 36781f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 36791f6eb021SLiane Praza * SCF_ERROR_DELETED 36801f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 36811f6eb021SLiane Praza * SCF_ERROR_INTERNAL 36821f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 36831f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 36841f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 36851f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 36861f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 36871f6eb021SLiane Praza */ 36881f6eb021SLiane Praza static int 36891f6eb021SLiane Praza _check_choices_include_values(scf_propertygroup_t *pg, const char *name) 36901f6eb021SLiane Praza { 36911f6eb021SLiane Praza int n = 0, r = 1; 36921f6eb021SLiane Praza char **ret; 36931f6eb021SLiane Praza scf_values_t vals; 36941f6eb021SLiane Praza 36951f6eb021SLiane Praza if ((ret = _read_astrings_values(pg, 36961f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES, &vals)) == NULL) { 36971f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 36981f6eb021SLiane Praza return (-1); 36991f6eb021SLiane Praza } else switch (scf_error()) { 37001f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 37011f6eb021SLiane Praza return (1); 37021f6eb021SLiane Praza 37031f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 37041f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 37051f6eb021SLiane Praza return (-1); 37061f6eb021SLiane Praza 37071f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 37081f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 37091f6eb021SLiane Praza default: 37101f6eb021SLiane Praza assert(0); 37111f6eb021SLiane Praza abort(); 37121f6eb021SLiane Praza } 37131f6eb021SLiane Praza } 37141f6eb021SLiane Praza 37151f6eb021SLiane Praza for (n = 0; n < vals.value_count; ++n) { 37161f6eb021SLiane Praza if (strcmp(name, ret[n]) == 0) { 37171f6eb021SLiane Praza r = 0; 37181f6eb021SLiane Praza break; 37191f6eb021SLiane Praza } 37201f6eb021SLiane Praza } 37211f6eb021SLiane Praza scf_values_destroy(&vals); 37221f6eb021SLiane Praza return (r); 37231f6eb021SLiane Praza } 37241f6eb021SLiane Praza 37251f6eb021SLiane Praza void 37261f6eb021SLiane Praza scf_count_ranges_destroy(scf_count_ranges_t *ranges) 37271f6eb021SLiane Praza { 37281f6eb021SLiane Praza if (ranges == NULL) 37291f6eb021SLiane Praza return; 37301f6eb021SLiane Praza 37311f6eb021SLiane Praza ranges->scr_num_ranges = 0; 37321f6eb021SLiane Praza free(ranges->scr_min); 37331f6eb021SLiane Praza free(ranges->scr_max); 37341f6eb021SLiane Praza ranges->scr_min = NULL; 37351f6eb021SLiane Praza ranges->scr_max = NULL; 37361f6eb021SLiane Praza } 37371f6eb021SLiane Praza 37381f6eb021SLiane Praza void 37391f6eb021SLiane Praza scf_int_ranges_destroy(scf_int_ranges_t *ranges) 37401f6eb021SLiane Praza { 37411f6eb021SLiane Praza if (ranges == NULL) 37421f6eb021SLiane Praza return; 37431f6eb021SLiane Praza 37441f6eb021SLiane Praza ranges->sir_num_ranges = 0; 37451f6eb021SLiane Praza free(ranges->sir_min); 37461f6eb021SLiane Praza free(ranges->sir_max); 37471f6eb021SLiane Praza ranges->sir_min = NULL; 37481f6eb021SLiane Praza ranges->sir_max = NULL; 37491f6eb021SLiane Praza } 37501f6eb021SLiane Praza 37511f6eb021SLiane Praza /* 37521f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 37531f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 37541f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 37551f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 37561f6eb021SLiane Praza * SCF_ERROR_DELETED 37571f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 37581f6eb021SLiane Praza * SCF_ERROR_INTERNAL 37591f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 37601f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 37611f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 37621f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 37631f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 37641f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 37651f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 37661f6eb021SLiane Praza */ 37671f6eb021SLiane Praza static int 37681f6eb021SLiane Praza _scf_tmpl_get_count_ranges(const scf_prop_tmpl_t *t, const char *prop, 37691f6eb021SLiane Praza scf_count_ranges_t *ranges) 37701f6eb021SLiane Praza { 37711f6eb021SLiane Praza scf_values_t vals; 37721f6eb021SLiane Praza int i = 0; 37731f6eb021SLiane Praza char **ret; 37741f6eb021SLiane Praza char *one_range[2]; 37751f6eb021SLiane Praza char *endptr; 37761f6eb021SLiane Praza char *str = NULL; 37771f6eb021SLiane Praza uint64_t *min = NULL; 37781f6eb021SLiane Praza uint64_t *max = NULL; 37791f6eb021SLiane Praza 37801f6eb021SLiane Praza assert(ranges != NULL); 37811f6eb021SLiane Praza if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL) 37821f6eb021SLiane Praza goto error; 37831f6eb021SLiane Praza if (vals.value_count == 0) { 37841f6eb021SLiane Praza /* range values are empty */ 37851f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 37861f6eb021SLiane Praza goto cleanup; 37871f6eb021SLiane Praza } 37881f6eb021SLiane Praza 37891f6eb021SLiane Praza min = malloc(vals.value_count * sizeof (uint64_t)); 37901f6eb021SLiane Praza max = malloc(vals.value_count * sizeof (uint64_t)); 37911f6eb021SLiane Praza if (min == NULL || max == NULL) { 37921f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 37931f6eb021SLiane Praza goto cleanup; 37941f6eb021SLiane Praza } 37951f6eb021SLiane Praza for (i = 0; i < vals.value_count; ++i) { 37961f6eb021SLiane Praza /* min and max should be separated by a "," */ 37971f6eb021SLiane Praza if ((str = _separate_by_separator(ret[i], ",", one_range, 37981f6eb021SLiane Praza 2)) == NULL) 37991f6eb021SLiane Praza goto cleanup; 38001f6eb021SLiane Praza errno = 0; 38011f6eb021SLiane Praza min[i] = strtoull(one_range[0], &endptr, 10); 38021f6eb021SLiane Praza if (errno != 0 || endptr == one_range[0] || *endptr) { 38031f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 38041f6eb021SLiane Praza goto cleanup; 38051f6eb021SLiane Praza } 38061f6eb021SLiane Praza errno = 0; 38071f6eb021SLiane Praza max[i] = strtoull(one_range[1], &endptr, 10); 38081f6eb021SLiane Praza if (errno != 0 || endptr == one_range[1] || *endptr) { 38091f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 38101f6eb021SLiane Praza goto cleanup; 38111f6eb021SLiane Praza } 38121f6eb021SLiane Praza if (min[i] > max[i]) { 38131f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 38141f6eb021SLiane Praza goto cleanup; 38151f6eb021SLiane Praza } 38161f6eb021SLiane Praza free(str); 38171f6eb021SLiane Praza str = NULL; 38181f6eb021SLiane Praza } 38191f6eb021SLiane Praza ranges->scr_num_ranges = vals.value_count; 38201f6eb021SLiane Praza ranges->scr_min = min; 38211f6eb021SLiane Praza ranges->scr_max = max; 38221f6eb021SLiane Praza scf_values_destroy(&vals); 38231f6eb021SLiane Praza return (0); 38241f6eb021SLiane Praza cleanup: 38251f6eb021SLiane Praza free(str); 38261f6eb021SLiane Praza free(min); 38271f6eb021SLiane Praza free(max); 38281f6eb021SLiane Praza scf_values_destroy(&vals); 38291f6eb021SLiane Praza error: 38301f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 38311f6eb021SLiane Praza return (-1); 38321f6eb021SLiane Praza } else switch (scf_error()) { 38331f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 38341f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 38351f6eb021SLiane Praza /*FALLTHROUGH*/ 38361f6eb021SLiane Praza 38371f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 38381f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 38391f6eb021SLiane Praza return (-1); 38401f6eb021SLiane Praza 38411f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 38421f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 38431f6eb021SLiane Praza default: 38441f6eb021SLiane Praza assert(0); 38451f6eb021SLiane Praza abort(); 38461f6eb021SLiane Praza } 38471f6eb021SLiane Praza /*NOTREACHED*/ 38481f6eb021SLiane Praza } 38491f6eb021SLiane Praza 38501f6eb021SLiane Praza /* 38511f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 38521f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 38531f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 38541f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 38551f6eb021SLiane Praza * SCF_ERROR_DELETED 38561f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 38571f6eb021SLiane Praza * SCF_ERROR_INTERNAL 38581f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 38591f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 38601f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 38611f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 38621f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 38631f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 38641f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 38651f6eb021SLiane Praza */ 38661f6eb021SLiane Praza static int 38671f6eb021SLiane Praza _scf_tmpl_get_int_ranges(const scf_prop_tmpl_t *t, const char *prop, 38681f6eb021SLiane Praza scf_int_ranges_t *ranges) 38691f6eb021SLiane Praza { 38701f6eb021SLiane Praza scf_values_t vals; 38711f6eb021SLiane Praza int n = 0; 38721f6eb021SLiane Praza char **ret; 38731f6eb021SLiane Praza char *one_range[2]; 38741f6eb021SLiane Praza char *endptr; 38751f6eb021SLiane Praza char *str = NULL; 38761f6eb021SLiane Praza int64_t *min = NULL; 38771f6eb021SLiane Praza int64_t *max = NULL; 38781f6eb021SLiane Praza 38791f6eb021SLiane Praza assert(ranges != NULL); 38801f6eb021SLiane Praza if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL) 38811f6eb021SLiane Praza goto error; 38821f6eb021SLiane Praza if (vals.value_count == 0) { 38831f6eb021SLiane Praza /* range values are empty */ 38841f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 38851f6eb021SLiane Praza goto cleanup; 38861f6eb021SLiane Praza } 38871f6eb021SLiane Praza 38881f6eb021SLiane Praza min = malloc(vals.value_count * sizeof (int64_t)); 38891f6eb021SLiane Praza max = malloc(vals.value_count * sizeof (int64_t)); 38901f6eb021SLiane Praza if (min == NULL || max == NULL) { 38911f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 38921f6eb021SLiane Praza goto cleanup; 38931f6eb021SLiane Praza } 38941f6eb021SLiane Praza while (n < vals.value_count) { 38951f6eb021SLiane Praza /* min and max should be separated by a "," */ 38961f6eb021SLiane Praza if ((str = _separate_by_separator(ret[n], ",", one_range, 2)) 38971f6eb021SLiane Praza == NULL) 38981f6eb021SLiane Praza goto cleanup; 38991f6eb021SLiane Praza errno = 0; 39001f6eb021SLiane Praza min[n] = strtoll(one_range[0], &endptr, 10); 39011f6eb021SLiane Praza if (errno != 0 || endptr == one_range[0] || *endptr) { 39021f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 39031f6eb021SLiane Praza goto cleanup; 39041f6eb021SLiane Praza } 39051f6eb021SLiane Praza errno = 0; 39061f6eb021SLiane Praza max[n] = strtoll(one_range[1], &endptr, 10); 39071f6eb021SLiane Praza if (errno != 0 || endptr == one_range[1] || *endptr) { 39081f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 39091f6eb021SLiane Praza goto cleanup; 39101f6eb021SLiane Praza } 39111f6eb021SLiane Praza if (min[n] > max[n]) { 39121f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 39131f6eb021SLiane Praza goto cleanup; 39141f6eb021SLiane Praza } 39151f6eb021SLiane Praza ++n; 39161f6eb021SLiane Praza free(str); 39171f6eb021SLiane Praza str = NULL; 39181f6eb021SLiane Praza } 39191f6eb021SLiane Praza ranges->sir_num_ranges = vals.value_count; 39201f6eb021SLiane Praza ranges->sir_min = min; 39211f6eb021SLiane Praza ranges->sir_max = max; 39221f6eb021SLiane Praza scf_values_destroy(&vals); 39231f6eb021SLiane Praza return (0); 39241f6eb021SLiane Praza cleanup: 39251f6eb021SLiane Praza free(str); 39261f6eb021SLiane Praza free(min); 39271f6eb021SLiane Praza free(max); 39281f6eb021SLiane Praza scf_values_destroy(&vals); 39291f6eb021SLiane Praza error: 39301f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 39311f6eb021SLiane Praza return (-1); 39321f6eb021SLiane Praza } else switch (scf_error()) { 39331f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 39341f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 39351f6eb021SLiane Praza /*FALLTHROUGH*/ 39361f6eb021SLiane Praza 39371f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 39381f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 39391f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 39401f6eb021SLiane Praza return (-1); 39411f6eb021SLiane Praza 39421f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 39431f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 39441f6eb021SLiane Praza default: 39451f6eb021SLiane Praza assert(0); 39461f6eb021SLiane Praza abort(); 39471f6eb021SLiane Praza } 39481f6eb021SLiane Praza /*NOTREACHED*/ 39491f6eb021SLiane Praza } 39501f6eb021SLiane Praza 39511f6eb021SLiane Praza /* 39521f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 39531f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 39541f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 39551f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 39561f6eb021SLiane Praza * SCF_ERROR_DELETED 39571f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 39581f6eb021SLiane Praza * SCF_ERROR_INTERNAL 39591f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 39601f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 39611f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 39621f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 39631f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 39641f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 39651f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 39661f6eb021SLiane Praza */ 39671f6eb021SLiane Praza int 39681f6eb021SLiane Praza scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t *t, 39691f6eb021SLiane Praza scf_count_ranges_t *ranges) 39701f6eb021SLiane Praza { 39711f6eb021SLiane Praza return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE, 39721f6eb021SLiane Praza ranges)); 39731f6eb021SLiane Praza } 39741f6eb021SLiane Praza 39751f6eb021SLiane Praza int 39761f6eb021SLiane Praza scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t *t, 39771f6eb021SLiane Praza scf_int_ranges_t *ranges) 39781f6eb021SLiane Praza { 39791f6eb021SLiane Praza return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE, 39801f6eb021SLiane Praza ranges)); 39811f6eb021SLiane Praza } 39821f6eb021SLiane Praza 39831f6eb021SLiane Praza int 39841f6eb021SLiane Praza scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t *t, 39851f6eb021SLiane Praza scf_count_ranges_t *ranges) 39861f6eb021SLiane Praza { 39871f6eb021SLiane Praza return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE, 39881f6eb021SLiane Praza ranges)); 39891f6eb021SLiane Praza } 39901f6eb021SLiane Praza 39911f6eb021SLiane Praza int 39921f6eb021SLiane Praza scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t *t, 39931f6eb021SLiane Praza scf_int_ranges_t *ranges) 39941f6eb021SLiane Praza { 39951f6eb021SLiane Praza return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE, 39961f6eb021SLiane Praza ranges)); 39971f6eb021SLiane Praza } 39981f6eb021SLiane Praza 39991f6eb021SLiane Praza /* 40001f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 40011f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 40021f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 40031f6eb021SLiane Praza * SCF_ERROR_DELETED 40041f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 40051f6eb021SLiane Praza * SCF_ERROR_INTERNAL 40061f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 40071f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 40081f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 40091f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 40101f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 40111f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 40121f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 40131f6eb021SLiane Praza */ 40141f6eb021SLiane Praza int 40151f6eb021SLiane Praza scf_tmpl_value_name_choices(const scf_prop_tmpl_t *t, scf_values_t *vals) 40161f6eb021SLiane Praza { 40171f6eb021SLiane Praza int c_flag = 0; /* have not read any value yet */ 40181f6eb021SLiane Praza int r; 40191f6eb021SLiane Praza char **ret; 40201f6eb021SLiane Praza 40211f6eb021SLiane Praza /* First, look for explicitly declared choices. */ 40221f6eb021SLiane Praza if ((ret = _read_astrings_values(t->prt_pg, 40231f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_NAME, vals)) != NULL) { 40241f6eb021SLiane Praza c_flag = 1; 40251f6eb021SLiane Praza } else if (scf_error() != SCF_ERROR_NOT_FOUND) { 40261f6eb021SLiane Praza goto error; 40271f6eb021SLiane Praza } 40281f6eb021SLiane Praza 40291f6eb021SLiane Praza /* Next, check for choices included by 'values'. */ 40301f6eb021SLiane Praza if ((r = _check_choices_include_values(t->prt_pg, "values")) == 0) { 40311f6eb021SLiane Praza /* read values_name */ 40321f6eb021SLiane Praza if (c_flag == 1) 40331f6eb021SLiane Praza /* append values */ 40341f6eb021SLiane Praza ret = _append_astrings_values(t->prt_pg, 40351f6eb021SLiane Praza SCF_PROPERTY_TM_VALUES_NAME, vals); 40361f6eb021SLiane Praza else 40371f6eb021SLiane Praza /* read values */ 40381f6eb021SLiane Praza ret = _read_astrings_values(t->prt_pg, 40391f6eb021SLiane Praza SCF_PROPERTY_TM_VALUES_NAME, vals); 40401f6eb021SLiane Praza if (ret != NULL) { 40411f6eb021SLiane Praza c_flag = 1; 40421f6eb021SLiane Praza } else if (scf_error() != SCF_ERROR_NOT_FOUND) { 40431f6eb021SLiane Praza goto error; 40441f6eb021SLiane Praza } 40451f6eb021SLiane Praza } else if (r == -1) { 40461f6eb021SLiane Praza goto error; 40471f6eb021SLiane Praza } 40481f6eb021SLiane Praza 40491f6eb021SLiane Praza /* Finally check for choices included by 'constraints'. */ 40501f6eb021SLiane Praza if ((r = _check_choices_include_values(t->prt_pg, "constraints")) == 40511f6eb021SLiane Praza 0) { 40521f6eb021SLiane Praza /* read constraint_name */ 40531f6eb021SLiane Praza if (c_flag == 1) 40541f6eb021SLiane Praza /* append values */ 40551f6eb021SLiane Praza ret = _append_astrings_values(t->prt_pg, 40561f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, vals); 40571f6eb021SLiane Praza else 40581f6eb021SLiane Praza /* read values */ 40591f6eb021SLiane Praza ret = _read_astrings_values(t->prt_pg, 40601f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, vals); 40611f6eb021SLiane Praza if (ret != NULL) { 40621f6eb021SLiane Praza c_flag = 1; 40631f6eb021SLiane Praza } else if (scf_error() != SCF_ERROR_NOT_FOUND) { 40641f6eb021SLiane Praza goto error; 40651f6eb021SLiane Praza } 40661f6eb021SLiane Praza } else if (r == -1) { 40671f6eb021SLiane Praza goto error; 40681f6eb021SLiane Praza } 40691f6eb021SLiane Praza 40701f6eb021SLiane Praza if (c_flag == 0 || vals->value_count == 0) { 40711f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 40721f6eb021SLiane Praza return (-1); 40731f6eb021SLiane Praza } 40741f6eb021SLiane Praza 40751f6eb021SLiane Praza return (0); 40761f6eb021SLiane Praza 40771f6eb021SLiane Praza error: 40781f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 40791f6eb021SLiane Praza return (-1); 40801f6eb021SLiane Praza } else switch (scf_error()) { 40811f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 40821f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 40831f6eb021SLiane Praza return (-1); 40841f6eb021SLiane Praza 40851f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 40861f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 40871f6eb021SLiane Praza default: 40881f6eb021SLiane Praza assert(0); 40891f6eb021SLiane Praza abort(); 40901f6eb021SLiane Praza } 40911f6eb021SLiane Praza /*NOTREACHED*/ 40921f6eb021SLiane Praza } 40931f6eb021SLiane Praza 40941f6eb021SLiane Praza void 40951f6eb021SLiane Praza scf_values_destroy(scf_values_t *vals) 40961f6eb021SLiane Praza { 40971f6eb021SLiane Praza int i; 40981f6eb021SLiane Praza char **items = NULL; 4099f6e214c7SGavin Maltby char **str = NULL; 41001f6eb021SLiane Praza 41011f6eb021SLiane Praza if (vals == NULL) 41021f6eb021SLiane Praza return; 41031f6eb021SLiane Praza 4104f6e214c7SGavin Maltby str = vals->values_as_strings; 4105f6e214c7SGavin Maltby 41061f6eb021SLiane Praza /* free values */ 41071f6eb021SLiane Praza switch (vals->value_type) { 41081f6eb021SLiane Praza case SCF_TYPE_BOOLEAN: 41091f6eb021SLiane Praza free(vals->values.v_boolean); 41101f6eb021SLiane Praza break; 41111f6eb021SLiane Praza case SCF_TYPE_COUNT: 41121f6eb021SLiane Praza free(vals->values.v_count); 41131f6eb021SLiane Praza break; 41141f6eb021SLiane Praza case SCF_TYPE_INTEGER: 41151f6eb021SLiane Praza free(vals->values.v_integer); 41161f6eb021SLiane Praza break; 41171f6eb021SLiane Praza case SCF_TYPE_ASTRING: 41181f6eb021SLiane Praza items = vals->values.v_astring; 41191f6eb021SLiane Praza str = NULL; 41201f6eb021SLiane Praza break; 41211f6eb021SLiane Praza case SCF_TYPE_USTRING: 41221f6eb021SLiane Praza items = vals->values.v_ustring; 41231f6eb021SLiane Praza str = NULL; 41241f6eb021SLiane Praza break; 41251f6eb021SLiane Praza case SCF_TYPE_OPAQUE: 41261f6eb021SLiane Praza items = vals->values.v_opaque; 41271f6eb021SLiane Praza str = NULL; 41281f6eb021SLiane Praza break; 41291f6eb021SLiane Praza case SCF_TYPE_TIME: 41301f6eb021SLiane Praza free(vals->values.v_time); 41311f6eb021SLiane Praza break; 41321f6eb021SLiane Praza default: 41331f6eb021SLiane Praza assert(0); 41341f6eb021SLiane Praza abort(); 41351f6eb021SLiane Praza } 41361f6eb021SLiane Praza for (i = 0; i < vals->value_count; ++i) { 41371f6eb021SLiane Praza if (items != NULL) 41381f6eb021SLiane Praza free(items[i]); 41391f6eb021SLiane Praza if (str != NULL) 41401f6eb021SLiane Praza free(str[i]); 41411f6eb021SLiane Praza } 41421f6eb021SLiane Praza vals->value_count = 0; 41431f6eb021SLiane Praza free(items); 41441f6eb021SLiane Praza free(str); 41451f6eb021SLiane Praza } 41461f6eb021SLiane Praza 41471f6eb021SLiane Praza /* 41481f6eb021SLiane Praza * char *_make_value_name() 41491f6eb021SLiane Praza * 41501f6eb021SLiane Praza * Construct the prefix for a value common name or value description property. 41511f6eb021SLiane Praza * It takes the form: 41521f6eb021SLiane Praza * value_<BASE32 name>_<common_name|description>_ 41531f6eb021SLiane Praza * This is then combined with a localized suffix by the caller to look 41541f6eb021SLiane Praza * up the property in the repository: 41551f6eb021SLiane Praza * value_<BASE32 name>_<common_name|description>_<lang> 41561f6eb021SLiane Praza * 41571f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 41581f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 41591f6eb021SLiane Praza * Name isn't short enough make a value name with. 41601f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 41611f6eb021SLiane Praza */ 41621f6eb021SLiane Praza static char * 41631f6eb021SLiane Praza _make_value_name(char *desc_name, const char *value) 41641f6eb021SLiane Praza { 41651f6eb021SLiane Praza char *name = NULL; 41661f6eb021SLiane Praza char *encoded = NULL; 41671f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 41681f6eb021SLiane Praza 41691f6eb021SLiane Praza name = malloc(sz); 41701f6eb021SLiane Praza encoded = malloc(sz); 41711f6eb021SLiane Praza if (name == NULL || encoded == NULL) { 41721f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 41731f6eb021SLiane Praza free(name); 41741f6eb021SLiane Praza free(encoded); 41751f6eb021SLiane Praza return (NULL); 41761f6eb021SLiane Praza } 41771f6eb021SLiane Praza 41781f6eb021SLiane Praza if (scf_encode32(value, strlen(value), encoded, sz, NULL, 41791f6eb021SLiane Praza SCF_ENCODE32_PAD) != 0) { 41801f6eb021SLiane Praza /* Shouldn't happen. */ 41811f6eb021SLiane Praza assert(0); 41821f6eb021SLiane Praza } 41831f6eb021SLiane Praza 41841f6eb021SLiane Praza (void) strlcpy(name, SCF_PROPERTY_TM_VALUE_PREFIX, sz); 41851f6eb021SLiane Praza 41861f6eb021SLiane Praza if (strlcat(name, encoded, sz) >= sz) { 41871f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 41881f6eb021SLiane Praza free(name); 41891f6eb021SLiane Praza free(encoded); 41901f6eb021SLiane Praza return (NULL); 41911f6eb021SLiane Praza } 41921f6eb021SLiane Praza 41931f6eb021SLiane Praza if (strlcat(name, "_", sz) >= sz) { 41941f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 41951f6eb021SLiane Praza free(name); 41961f6eb021SLiane Praza free(encoded); 41971f6eb021SLiane Praza return (NULL); 41981f6eb021SLiane Praza } 41991f6eb021SLiane Praza 42001f6eb021SLiane Praza if (strlcat(name, desc_name, sz) >= sz) { 42011f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 42021f6eb021SLiane Praza free(name); 42031f6eb021SLiane Praza free(encoded); 42041f6eb021SLiane Praza return (NULL); 42051f6eb021SLiane Praza } 42061f6eb021SLiane Praza 42071f6eb021SLiane Praza if (strlcat(name, "_", sz) >= sz) { 42081f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 42091f6eb021SLiane Praza free(name); 42101f6eb021SLiane Praza free(encoded); 42111f6eb021SLiane Praza return (NULL); 42121f6eb021SLiane Praza } 42131f6eb021SLiane Praza 42141f6eb021SLiane Praza free(encoded); 42151f6eb021SLiane Praza return (name); 42161f6eb021SLiane Praza } 42171f6eb021SLiane Praza 42181f6eb021SLiane Praza /* 42191f6eb021SLiane Praza * ssize_t scf_tmpl_value_common_name() 42201f6eb021SLiane Praza * 42211f6eb021SLiane Praza * Populates "out" with an allocated string containing the value's 42221f6eb021SLiane Praza * common name. Returns the size of the string on successful return. 42231f6eb021SLiane Praza * out must be freed with free() on successful return. 42241f6eb021SLiane Praza * 42251f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 42261f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 42271f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 42281f6eb021SLiane Praza * SCF_ERROR_DELETED 42291f6eb021SLiane Praza * Property group was deleted. 42301f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 42311f6eb021SLiane Praza * SCF_ERROR_INTERNAL 42321f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 42331f6eb021SLiane Praza * name not a valid property name 42341f6eb021SLiane Praza * name and locale are too long to make a property name 42351f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 42361f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 42371f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 42381f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 42391f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 42401f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 42411f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 42421f6eb021SLiane Praza * property is not SCF_TYPE_ASTRING has more than one value. 42431f6eb021SLiane Praza */ 42441f6eb021SLiane Praza ssize_t 42451f6eb021SLiane Praza scf_tmpl_value_common_name(const scf_prop_tmpl_t *t, const char *locale, 42461f6eb021SLiane Praza const char *value, char **out) 42471f6eb021SLiane Praza { 42481f6eb021SLiane Praza char *value_name = NULL; 42491f6eb021SLiane Praza 42501f6eb021SLiane Praza value_name = _make_value_name("common_name", value); 42511f6eb021SLiane Praza if (value_name == NULL) 42521f6eb021SLiane Praza return (-1); 42531f6eb021SLiane Praza 42541f6eb021SLiane Praza *out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale); 42551f6eb021SLiane Praza 42561f6eb021SLiane Praza free(value_name); 42571f6eb021SLiane Praza 42581f6eb021SLiane Praza if (*out == NULL) 42591f6eb021SLiane Praza return (-1); 42601f6eb021SLiane Praza 42611f6eb021SLiane Praza return (strlen(*out)); 42621f6eb021SLiane Praza } 42631f6eb021SLiane Praza 42641f6eb021SLiane Praza /* 42651f6eb021SLiane Praza * ssize_t scf_tmpl_value_description() 42661f6eb021SLiane Praza * 42671f6eb021SLiane Praza * Populates "out" with an allocated string containing the value's 42681f6eb021SLiane Praza * description. Returns the size of the string on successful return. 42691f6eb021SLiane Praza * out must be freed with free() on successful return. 42701f6eb021SLiane Praza * 42711f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 42721f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 42731f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 42741f6eb021SLiane Praza * SCF_ERROR_DELETED 42751f6eb021SLiane Praza * Property group was deleted. 42761f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 42771f6eb021SLiane Praza * SCF_ERROR_INTERNAL 42781f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 42791f6eb021SLiane Praza * name not a valid property name 42801f6eb021SLiane Praza * name and locale are too long to make a property name 42811f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 42821f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 42831f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 42841f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 42851f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 42861f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 42871f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 42881f6eb021SLiane Praza * property is not SCF_TYPE_ASTRING has more than one value. 42891f6eb021SLiane Praza */ 42901f6eb021SLiane Praza ssize_t 42911f6eb021SLiane Praza scf_tmpl_value_description(const scf_prop_tmpl_t *t, const char *locale, 42921f6eb021SLiane Praza const char *value, char **out) 42931f6eb021SLiane Praza { 42941f6eb021SLiane Praza char *value_name = NULL; 42951f6eb021SLiane Praza 42961f6eb021SLiane Praza value_name = _make_value_name("description", value); 42971f6eb021SLiane Praza if (value_name == NULL) 42981f6eb021SLiane Praza return (-1); 42991f6eb021SLiane Praza 43001f6eb021SLiane Praza 43011f6eb021SLiane Praza *out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale); 43021f6eb021SLiane Praza 43031f6eb021SLiane Praza free(value_name); 43041f6eb021SLiane Praza 43051f6eb021SLiane Praza if (*out == NULL) 43061f6eb021SLiane Praza return (-1); 43071f6eb021SLiane Praza 43081f6eb021SLiane Praza return (strlen(*out)); 43091f6eb021SLiane Praza } 43101f6eb021SLiane Praza 43111f6eb021SLiane Praza /* 43121f6eb021SLiane Praza * Templates error messages format, in human readable form. 43131f6eb021SLiane Praza * Each line is one error item: 43141f6eb021SLiane Praza * 43151f6eb021SLiane Praza * prefix error message 43161f6eb021SLiane Praza * FMRI="err->te_errs->tes_fmri" 43171f6eb021SLiane Praza * Property group="err->te_pg_name" 43181f6eb021SLiane Praza * Property name="err->te_prop_name" 43191f6eb021SLiane Praza * expected value 1="err->te_ev1" 43201f6eb021SLiane Praza * expected value 2="err->te_ev2" 43211f6eb021SLiane Praza * actual value="err->te_actual" 43221f6eb021SLiane Praza * Tempalte source="err->te_tmpl_fmri" 43231f6eb021SLiane Praza * pg_pattern name="err->tmpl_pg_name" 43241f6eb021SLiane Praza * pg_pattern type="err->tmpl_pg_type" 43251f6eb021SLiane Praza * prop_pattern name="err->tmpl_prop_name" 43261f6eb021SLiane Praza * prop_pattern type="err->tmpl_prop_type" 43271f6eb021SLiane Praza * 43281f6eb021SLiane Praza * To add a new error type, include scf_tmpl_error_type_t in libscf.h 43291f6eb021SLiane Praza * add one entry in em_desc[], and update the functions pointed by the 43301f6eb021SLiane Praza * _tmpl_error_access array with the new error code. Also, update the 43311f6eb021SLiane Praza * scf_tmpl_error_* functions to provide access to desired 43321f6eb021SLiane Praza * scf_tmpl_error_t fields. 43331f6eb021SLiane Praza * 43341f6eb021SLiane Praza * To add a new error item, add a new field to scf_tmpl_error_t, a new field 43351f6eb021SLiane Praza * in _scf_tmpl_error_desc or a new non-error-dependent string, add a new entry 43361f6eb021SLiane Praza * in _tmpl_error_access array and create the appropriate get_val, get_desc 43371f6eb021SLiane Praza * functions. 43381f6eb021SLiane Praza * 43391f6eb021SLiane Praza * Changes to both the validation logic and the error types and items must 43401f6eb021SLiane Praza * be coordinated with the code in svccfg to ensure both libscf and svccfg's 43411f6eb021SLiane Praza * manifest validation validate the same things. 43421f6eb021SLiane Praza */ 43431f6eb021SLiane Praza 43441f6eb021SLiane Praza /* 43451f6eb021SLiane Praza * Container for all template errors on a validated object. 43461f6eb021SLiane Praza */ 43471f6eb021SLiane Praza struct scf_tmpl_errors { 43481f6eb021SLiane Praza int tes_index; 43491f6eb021SLiane Praza int tes_num_errs; 43501f6eb021SLiane Praza scf_tmpl_error_t **tes_errs; 43511f6eb021SLiane Praza int tes_errs_size; 43521f6eb021SLiane Praza const char *tes_fmri; 43531f6eb021SLiane Praza const char *tes_prefix; 43541f6eb021SLiane Praza int tes_flag; /* if set, scf_tmpl_error_destroy */ 43551f6eb021SLiane Praza /* will free strings in tes_errs */ 43561f6eb021SLiane Praza }; 43571f6eb021SLiane Praza 43581f6eb021SLiane Praza /* 43591f6eb021SLiane Praza * Templates error-dependent labels 43601f6eb021SLiane Praza */ 43611f6eb021SLiane Praza struct _scf_tmpl_error_desc { 43621f6eb021SLiane Praza const char *em_msg; 43631f6eb021SLiane Praza const char *em_ev1; 43641f6eb021SLiane Praza const char *em_ev2; 43651f6eb021SLiane Praza const char *em_actual; 43661f6eb021SLiane Praza }; 43671f6eb021SLiane Praza 43681f6eb021SLiane Praza /* 43691f6eb021SLiane Praza * This array MUST be kept in synch with the template error definition of 43701f6eb021SLiane Praza * scf_tmpl_error_type_t in libscf.h 43711f6eb021SLiane Praza */ 43721f6eb021SLiane Praza static struct _scf_tmpl_error_desc em_desc[] = { 43731f6eb021SLiane Praza /* SCF_TERR_MISSING_PG */ 43741f6eb021SLiane Praza { "Required property group missing", "Name of missing property group", 43751f6eb021SLiane Praza "Type of missing property group", NULL }, 43761f6eb021SLiane Praza /* SCF_TERR_WRONG_PG_TYPE */ 43771f6eb021SLiane Praza { "Property group has bad type", "Specified type", NULL, 43781f6eb021SLiane Praza "Actual type" }, 43791f6eb021SLiane Praza /* SCF_TERR_MISSING_PROP */ 43801f6eb021SLiane Praza { "Required property missing", "Name of missing property", NULL, NULL }, 43811f6eb021SLiane Praza /* SCF_TERR_WRONG_PROP_TYPE */ 43821f6eb021SLiane Praza { "Property has bad type", "Specified property type", NULL, 43831f6eb021SLiane Praza "Actual property type" }, 43841f6eb021SLiane Praza /* SCF_TERR_CARDINALITY_VIOLATION */ 43851f6eb021SLiane Praza { "Number of property values violates cardinality restriction", 43861f6eb021SLiane Praza "Cardinality minimum", "Cardinality maximum", 43871f6eb021SLiane Praza "Actual number of values" }, 43881f6eb021SLiane Praza /* SCF_TERR_VALUE_CONSTRAINT_VIOLATED */ 43891f6eb021SLiane Praza { "Property has illegal value", NULL, NULL, "Illegal value" }, 43901f6eb021SLiane Praza /* SCF_TERR_RANGE_VIOLATION */ 43911f6eb021SLiane Praza { "Property value is out of range", NULL, NULL, "Actual value" }, 43921f6eb021SLiane Praza /* SCF_TERR_PG_REDEFINE */ 43931f6eb021SLiane Praza { "Instance redefines pg_pattern", "Instance pg_pattern name", 43941f6eb021SLiane Praza "Instance pg_pattern type", NULL }, 43951f6eb021SLiane Praza /* SCF_TERR_PROP_TYPE_MISMATCH */ 43961f6eb021SLiane Praza { "Property type and value type mismatch", NULL, NULL, "Value type" }, 43971f6eb021SLiane Praza /* SCF_TERR_VALUE_OUT_OF_RANGE */ 43981f6eb021SLiane Praza { "Value is out of range", NULL, NULL, "Value" }, 43991f6eb021SLiane Praza /* SCF_TERR_INVALID_VALUE */ 44001f6eb021SLiane Praza { "Value is not valid", NULL, NULL, "Value" }, 44011f6eb021SLiane Praza /* SCF_TERR_PG_PATTERN_CONFLICT */ 44021f6eb021SLiane Praza { "Conflicting pg_pattern specifications", "Template source", 44031f6eb021SLiane Praza "pg_pattern name", "pg_pattern type" }, 44041f6eb021SLiane Praza /* SCF_TERR_PROP_PATTERN_CONFLICT */ 44051f6eb021SLiane Praza { "Conflicting prop_pattern specifications", "Template source", 44061f6eb021SLiane Praza "prop_pattern name", "prop_pattern type" }, 44071f6eb021SLiane Praza /* SCF_TERR_GENERAL_REDEFINE */ 44081f6eb021SLiane Praza { "Service or instance pg_pattern redefines a global or restarter " 44091f6eb021SLiane Praza "pg_pattern", "Template source", "pg_pattern name", 44101f6eb021SLiane Praza "pg_pattern type" }, 44111f6eb021SLiane Praza /* SCF_TERR_INCLUDE_VALUES */ 44121f6eb021SLiane Praza { "Missing constraints or values for include_values element", 44131f6eb021SLiane Praza "include_values type", NULL, NULL }, 44141f6eb021SLiane Praza /* SCF_TERR_PG_PATTERN_INCOMPLETE */ 44151f6eb021SLiane Praza { "Required pg_pattern is missing a name or type attribute", 44161f6eb021SLiane Praza NULL, NULL, NULL }, 44171f6eb021SLiane Praza /* SCF_TERR_PROP_PATTERN_INCOMPLETE */ 44181f6eb021SLiane Praza { "Required prop_pattern is missing a type attribute", 44191f6eb021SLiane Praza NULL, NULL, NULL } 44201f6eb021SLiane Praza }; 44211f6eb021SLiane Praza 44221f6eb021SLiane Praza /* 44231f6eb021SLiane Praza * Templates non error-dependent labels 44241f6eb021SLiane Praza */ 44251f6eb021SLiane Praza static const char *em_fmri = "FMRI"; 44261f6eb021SLiane Praza static const char *em_pg_name = "Property group"; 44271f6eb021SLiane Praza static const char *em_prop_name = "Property name"; 44281f6eb021SLiane Praza static const char *em_tmpl_fmri = "Template source"; 44291f6eb021SLiane Praza static const char *em_tmpl_pg_name = "pg_pattern name"; 44301f6eb021SLiane Praza static const char *em_tmpl_pg_type = "pg_pattern type"; 44311f6eb021SLiane Praza static const char *em_tmpl_prop_name = "prop_pattern name"; 44321f6eb021SLiane Praza static const char *em_tmpl_prop_type = "prop_pattern type"; 44331f6eb021SLiane Praza 44341f6eb021SLiane Praza static const char * 44351f6eb021SLiane Praza _get_fmri_desc(scf_tmpl_error_t *err) 44361f6eb021SLiane Praza { 44371f6eb021SLiane Praza switch (err->te_type) { 44381f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 44391f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 44401f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 44411f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 44421f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 44431f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 44441f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 44451f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 44461f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 44471f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 44481f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 44491f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_fmri)); 44501f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 44511f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 44521f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 44531f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 44541f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 44551f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 44561f6eb021SLiane Praza default: 44571f6eb021SLiane Praza return (NULL); 44581f6eb021SLiane Praza } 44591f6eb021SLiane Praza } 44601f6eb021SLiane Praza 44611f6eb021SLiane Praza static const char * 44621f6eb021SLiane Praza _get_pg_name_desc(scf_tmpl_error_t *err) 44631f6eb021SLiane Praza { 44641f6eb021SLiane Praza switch (err->te_type) { 44651f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 44661f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 44671f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 44681f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 44691f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 44701f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 44711f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_pg_name)); 44721f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 44731f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 44741f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 44751f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 44761f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 44771f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 44781f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 44791f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 44801f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 44811f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 44821f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 44831f6eb021SLiane Praza default: 44841f6eb021SLiane Praza return (NULL); 44851f6eb021SLiane Praza } 44861f6eb021SLiane Praza } 44871f6eb021SLiane Praza 44881f6eb021SLiane Praza static const char * 44891f6eb021SLiane Praza _get_prop_name_desc(scf_tmpl_error_t *err) 44901f6eb021SLiane Praza { 44911f6eb021SLiane Praza switch (err->te_type) { 44921f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 44931f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 44941f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 44951f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 44961f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_prop_name)); 44971f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 44981f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 44991f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 45001f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 45011f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 45021f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 45031f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 45041f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 45051f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 45061f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 45071f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 45081f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 45091f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 45101f6eb021SLiane Praza default: 45111f6eb021SLiane Praza return (NULL); 45121f6eb021SLiane Praza } 45131f6eb021SLiane Praza } 45141f6eb021SLiane Praza 45151f6eb021SLiane Praza static const char * 45161f6eb021SLiane Praza _get_ev1_desc(scf_tmpl_error_t *err) 45171f6eb021SLiane Praza { 45181f6eb021SLiane Praza switch (err->te_type) { 45191f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 45201f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 45211f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 45221f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 45231f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 45241f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 45251f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 45261f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 45271f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 45281f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 45291f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 45301f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev1)); 45311f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 45321f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 45331f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 45341f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 45351f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 45361f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 45371f6eb021SLiane Praza default: 45381f6eb021SLiane Praza return (NULL); 45391f6eb021SLiane Praza } 45401f6eb021SLiane Praza } 45411f6eb021SLiane Praza 45421f6eb021SLiane Praza static const char * 45431f6eb021SLiane Praza _get_ev2_desc(scf_tmpl_error_t *err) 45441f6eb021SLiane Praza { 45451f6eb021SLiane Praza switch (err->te_type) { 45461f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 45471f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 45481f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 45491f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 45501f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 45511f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 45521f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 45531f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev2)); 45541f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 45551f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 45561f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 45571f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 45581f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 45591f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 45601f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 45611f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 45621f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 45631f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 45641f6eb021SLiane Praza default: 45651f6eb021SLiane Praza return (NULL); 45661f6eb021SLiane Praza } 45671f6eb021SLiane Praza } 45681f6eb021SLiane Praza 45691f6eb021SLiane Praza static const char * 45701f6eb021SLiane Praza _get_actual_desc(scf_tmpl_error_t *err) 45711f6eb021SLiane Praza { 45721f6eb021SLiane Praza switch (err->te_type) { 45731f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 45741f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 45751f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 45761f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 45771f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 45781f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 45791f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 45801f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 45811f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 45821f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 45831f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 45841f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 45851f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 45861f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, 45871f6eb021SLiane Praza em_desc[err->te_type].em_actual)); 45881f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 45891f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 45901f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 45911f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 45921f6eb021SLiane Praza default: 45931f6eb021SLiane Praza return (NULL); 45941f6eb021SLiane Praza } 45951f6eb021SLiane Praza } 45961f6eb021SLiane Praza 45971f6eb021SLiane Praza static const char * 45981f6eb021SLiane Praza _get_tmpl_fmri_desc(scf_tmpl_error_t *err) 45991f6eb021SLiane Praza { 46001f6eb021SLiane Praza switch (err->te_type) { 46011f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 46021f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 46031f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 46041f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 46051f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 46061f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 46071f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 46081f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 46091f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 46101f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 46111f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 46121f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 46131f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 46141f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 46151f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 46161f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 46171f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 46181f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_fmri)); 46191f6eb021SLiane Praza default: 46201f6eb021SLiane Praza return (NULL); 46211f6eb021SLiane Praza } 46221f6eb021SLiane Praza } 46231f6eb021SLiane Praza 46241f6eb021SLiane Praza static const char * 46251f6eb021SLiane Praza _get_tmpl_pg_name_desc(scf_tmpl_error_t *err) 46261f6eb021SLiane Praza { 46271f6eb021SLiane Praza switch (err->te_type) { 46281f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 46291f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 46301f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 46311f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 46321f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 46331f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 46341f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 46351f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 46361f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 46371f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 46381f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 46391f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 46401f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 46411f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 46421f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 46431f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 46441f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 46451f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_pg_name)); 46461f6eb021SLiane Praza default: 46471f6eb021SLiane Praza return (NULL); 46481f6eb021SLiane Praza } 46491f6eb021SLiane Praza } 46501f6eb021SLiane Praza 46511f6eb021SLiane Praza static const char * 46521f6eb021SLiane Praza _get_tmpl_pg_type_desc(scf_tmpl_error_t *err) 46531f6eb021SLiane Praza { 46541f6eb021SLiane Praza switch (err->te_type) { 46551f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 46561f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 46571f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 46581f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 46591f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 46601f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 46611f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 46621f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 46631f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 46641f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 46651f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 46661f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 46671f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 46681f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 46691f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 46701f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 46711f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 46721f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_pg_type)); 46731f6eb021SLiane Praza default: 46741f6eb021SLiane Praza return (NULL); 46751f6eb021SLiane Praza } 46761f6eb021SLiane Praza } 46771f6eb021SLiane Praza 46781f6eb021SLiane Praza static const char * 46791f6eb021SLiane Praza _get_tmpl_prop_name_desc(scf_tmpl_error_t *err) 46801f6eb021SLiane Praza { 46811f6eb021SLiane Praza switch (err->te_type) { 46821f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 46831f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 46841f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 46851f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 46861f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 46871f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 46881f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 46891f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 46901f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 46911f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 46921f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 46931f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_prop_name)); 46941f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 46951f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 46961f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 46971f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 46981f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 46991f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 47001f6eb021SLiane Praza default: 47011f6eb021SLiane Praza return (NULL); 47021f6eb021SLiane Praza } 47031f6eb021SLiane Praza } 47041f6eb021SLiane Praza 47051f6eb021SLiane Praza static const char * 47061f6eb021SLiane Praza _get_tmpl_prop_type_desc(scf_tmpl_error_t *err) 47071f6eb021SLiane Praza { 47081f6eb021SLiane Praza switch (err->te_type) { 47091f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 47101f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 47111f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 47121f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 47131f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 47141f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 47151f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 47161f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 47171f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 47181f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 47191f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_prop_type)); 47201f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 47211f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 47221f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 47231f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 47241f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 47251f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 47261f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 47271f6eb021SLiane Praza default: 47281f6eb021SLiane Praza return (NULL); 47291f6eb021SLiane Praza } 47301f6eb021SLiane Praza } 47311f6eb021SLiane Praza 47321f6eb021SLiane Praza static const char * 47331f6eb021SLiane Praza _get_fmri_val(scf_tmpl_error_t *err) 47341f6eb021SLiane Praza { 47351f6eb021SLiane Praza assert(err != NULL && err->te_errs != NULL && 47361f6eb021SLiane Praza err->te_errs->tes_fmri != NULL); 47371f6eb021SLiane Praza return (err->te_errs->tes_fmri); 47381f6eb021SLiane Praza } 47391f6eb021SLiane Praza 47401f6eb021SLiane Praza static const char * 47411f6eb021SLiane Praza _get_pg_name_val(scf_tmpl_error_t *err) 47421f6eb021SLiane Praza { 47431f6eb021SLiane Praza assert(err != NULL); 47441f6eb021SLiane Praza return (err->te_pg_name); 47451f6eb021SLiane Praza } 47461f6eb021SLiane Praza 47471f6eb021SLiane Praza static const char * 47481f6eb021SLiane Praza _get_prop_name_val(scf_tmpl_error_t *err) 47491f6eb021SLiane Praza { 47501f6eb021SLiane Praza assert(err != NULL); 47511f6eb021SLiane Praza return (err->te_prop_name); 47521f6eb021SLiane Praza } 47531f6eb021SLiane Praza 47541f6eb021SLiane Praza static const char * 47551f6eb021SLiane Praza _get_ev1_val(scf_tmpl_error_t *err) 47561f6eb021SLiane Praza { 47571f6eb021SLiane Praza assert(err != NULL); 47581f6eb021SLiane Praza return (err->te_ev1); 47591f6eb021SLiane Praza } 47601f6eb021SLiane Praza 47611f6eb021SLiane Praza static const char * 47621f6eb021SLiane Praza _get_ev2_val(scf_tmpl_error_t *err) 47631f6eb021SLiane Praza { 47641f6eb021SLiane Praza assert(err != NULL); 47651f6eb021SLiane Praza return (err->te_ev2); 47661f6eb021SLiane Praza } 47671f6eb021SLiane Praza 47681f6eb021SLiane Praza static const char * 47691f6eb021SLiane Praza _get_actual_val(scf_tmpl_error_t *err) 47701f6eb021SLiane Praza { 47711f6eb021SLiane Praza assert(err != NULL); 47721f6eb021SLiane Praza return (err->te_actual); 47731f6eb021SLiane Praza } 47741f6eb021SLiane Praza 47751f6eb021SLiane Praza static const char * 47761f6eb021SLiane Praza _get_tmpl_fmri_val(scf_tmpl_error_t *err) 47771f6eb021SLiane Praza { 47781f6eb021SLiane Praza assert(err != NULL); 47791f6eb021SLiane Praza return (err->te_tmpl_fmri); 47801f6eb021SLiane Praza } 47811f6eb021SLiane Praza 47821f6eb021SLiane Praza static const char * 47831f6eb021SLiane Praza _get_tmpl_pg_name_val(scf_tmpl_error_t *err) 47841f6eb021SLiane Praza { 47851f6eb021SLiane Praza assert(err != NULL); 47861f6eb021SLiane Praza return (err->te_tmpl_pg_name); 47871f6eb021SLiane Praza } 47881f6eb021SLiane Praza 47891f6eb021SLiane Praza static const char * 47901f6eb021SLiane Praza _get_tmpl_pg_type_val(scf_tmpl_error_t *err) 47911f6eb021SLiane Praza { 47921f6eb021SLiane Praza assert(err != NULL); 47931f6eb021SLiane Praza return (err->te_tmpl_pg_type); 47941f6eb021SLiane Praza } 47951f6eb021SLiane Praza 47961f6eb021SLiane Praza static const char * 47971f6eb021SLiane Praza _get_tmpl_prop_name_val(scf_tmpl_error_t *err) 47981f6eb021SLiane Praza { 47991f6eb021SLiane Praza assert(err != NULL); 48001f6eb021SLiane Praza return (err->te_tmpl_prop_name); 48011f6eb021SLiane Praza } 48021f6eb021SLiane Praza 48031f6eb021SLiane Praza static const char * 48041f6eb021SLiane Praza _get_tmpl_prop_type_val(scf_tmpl_error_t *err) 48051f6eb021SLiane Praza { 48061f6eb021SLiane Praza assert(err != NULL); 48071f6eb021SLiane Praza return (err->te_tmpl_prop_type); 48081f6eb021SLiane Praza } 48091f6eb021SLiane Praza 48101f6eb021SLiane Praza /* 48111f6eb021SLiane Praza * Templates error item retrival functions 48121f6eb021SLiane Praza */ 48131f6eb021SLiane Praza typedef const char *(*get_em)(scf_tmpl_error_t *); 48141f6eb021SLiane Praza 48151f6eb021SLiane Praza /* 48161f6eb021SLiane Praza * if new items (lines) are added to the templates error messages, 48171f6eb021SLiane Praza * new entries in this array (and new fuctions) will be required. 48181f6eb021SLiane Praza */ 48191f6eb021SLiane Praza static struct _tmpl_error_access { 48201f6eb021SLiane Praza get_em get_desc; 48211f6eb021SLiane Praza get_em get_val; 48221f6eb021SLiane Praza } _tmpl_error_items[] = { 48231f6eb021SLiane Praza { (get_em)_get_fmri_desc, (get_em)_get_fmri_val }, 48241f6eb021SLiane Praza { (get_em)_get_pg_name_desc, (get_em)_get_pg_name_val }, 48251f6eb021SLiane Praza { (get_em)_get_prop_name_desc, (get_em)_get_prop_name_val }, 48261f6eb021SLiane Praza { (get_em)_get_ev1_desc, (get_em)_get_ev1_val }, 48271f6eb021SLiane Praza { (get_em)_get_ev2_desc, (get_em)_get_ev2_val }, 48281f6eb021SLiane Praza { (get_em)_get_actual_desc, (get_em)_get_actual_val }, 48291f6eb021SLiane Praza { (get_em)_get_tmpl_fmri_desc, (get_em)_get_tmpl_fmri_val }, 48301f6eb021SLiane Praza { (get_em)_get_tmpl_pg_name_desc, (get_em)_get_tmpl_pg_name_val }, 48311f6eb021SLiane Praza { (get_em)_get_tmpl_pg_type_desc, (get_em)_get_tmpl_pg_type_val }, 48321f6eb021SLiane Praza { (get_em)_get_tmpl_prop_name_desc, (get_em)_get_tmpl_prop_name_val }, 48331f6eb021SLiane Praza { (get_em)_get_tmpl_prop_type_desc, (get_em)_get_tmpl_prop_type_val }, 48341f6eb021SLiane Praza { NULL } 48351f6eb021SLiane Praza }; 48361f6eb021SLiane Praza 48371f6eb021SLiane Praza /* 48381f6eb021SLiane Praza * Allocate a new scf_tmpl_error_t and add it to the errs list provided. 48391f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 48401f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 48411f6eb021SLiane Praza */ 48421f6eb021SLiane Praza static scf_tmpl_error_t * 48431f6eb021SLiane Praza _create_error(scf_tmpl_errors_t *errs) 48441f6eb021SLiane Praza { 48451f6eb021SLiane Praza scf_tmpl_error_t *ret; 48461f6eb021SLiane Praza scf_tmpl_error_t **saved_errs; 48471f6eb021SLiane Praza 48481f6eb021SLiane Praza assert(errs != NULL); 48491f6eb021SLiane Praza ret = calloc(1, sizeof (scf_tmpl_error_t)); 48501f6eb021SLiane Praza if (ret == NULL) { 48511f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 48521f6eb021SLiane Praza return (NULL); 48531f6eb021SLiane Praza } 48541f6eb021SLiane Praza 48551f6eb021SLiane Praza ret->te_errs = errs; 48561f6eb021SLiane Praza 48571f6eb021SLiane Praza assert(errs->tes_num_errs <= errs->tes_errs_size); 48581f6eb021SLiane Praza if (errs->tes_num_errs == errs->tes_errs_size) { 48591f6eb021SLiane Praza /* Time to grow the pointer array. */ 48601f6eb021SLiane Praza saved_errs = errs->tes_errs; 48611f6eb021SLiane Praza errs->tes_errs = calloc(2 * errs->tes_errs_size, 48621f6eb021SLiane Praza sizeof (scf_tmpl_error_t *)); 48631f6eb021SLiane Praza if (errs->tes_errs == NULL) { 48641f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 48651f6eb021SLiane Praza errs->tes_errs = saved_errs; 48661f6eb021SLiane Praza free(ret); 48671f6eb021SLiane Praza return (NULL); 48681f6eb021SLiane Praza } 48691f6eb021SLiane Praza (void) memcpy(errs->tes_errs, saved_errs, errs->tes_errs_size * 48701f6eb021SLiane Praza sizeof (scf_tmpl_error_t *)); 48711f6eb021SLiane Praza errs->tes_errs_size = 2 * errs->tes_errs_size; 48721f6eb021SLiane Praza free(saved_errs); 48731f6eb021SLiane Praza } 48741f6eb021SLiane Praza 48751f6eb021SLiane Praza errs->tes_errs[errs->tes_num_errs] = ret; 48761f6eb021SLiane Praza errs->tes_num_errs++; 48771f6eb021SLiane Praza 48781f6eb021SLiane Praza return (ret); 48791f6eb021SLiane Praza } 48801f6eb021SLiane Praza 48811f6eb021SLiane Praza /* 48821f6eb021SLiane Praza * 48831f6eb021SLiane Praza * If destroy_strings is set, scf_tmpl_errors_destroy will free the 48841f6eb021SLiane Praza * strings in scf_tmpl_error_t entries. 48851f6eb021SLiane Praza * 48861f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 48871f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 48881f6eb021SLiane Praza */ 48891f6eb021SLiane Praza scf_tmpl_errors_t * 48901f6eb021SLiane Praza _scf_create_errors(const char *fmri, int destroy_strings) 48911f6eb021SLiane Praza { 48921f6eb021SLiane Praza scf_tmpl_errors_t *ret; 48931f6eb021SLiane Praza int errs_size = 20; 48941f6eb021SLiane Praza 48951f6eb021SLiane Praza assert(fmri != NULL); 48961f6eb021SLiane Praza 48971f6eb021SLiane Praza ret = calloc(1, sizeof (scf_tmpl_errors_t)); 48981f6eb021SLiane Praza if (ret == NULL) { 48991f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 49001f6eb021SLiane Praza return (NULL); 49011f6eb021SLiane Praza } 49021f6eb021SLiane Praza 49031f6eb021SLiane Praza ret->tes_index = 0; 49041f6eb021SLiane Praza ret->tes_num_errs = 0; 49051f6eb021SLiane Praza if ((ret->tes_fmri = strdup(fmri)) == NULL) { 49061f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 49071f6eb021SLiane Praza free(ret); 49081f6eb021SLiane Praza return (NULL); 49091f6eb021SLiane Praza } 49101f6eb021SLiane Praza 49111f6eb021SLiane Praza ret->tes_prefix = strdup(""); 49121f6eb021SLiane Praza if (ret->tes_prefix == NULL) { 49131f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 49141f6eb021SLiane Praza free((char *)ret->tes_fmri); 49151f6eb021SLiane Praza free(ret); 49161f6eb021SLiane Praza return (NULL); 49171f6eb021SLiane Praza } 49181f6eb021SLiane Praza ret->tes_flag = destroy_strings; 49191f6eb021SLiane Praza 49201f6eb021SLiane Praza /* Make space for a few errors. */ 49211f6eb021SLiane Praza ret->tes_errs = calloc(errs_size, sizeof (scf_tmpl_error_t *)); 49221f6eb021SLiane Praza if (ret->tes_errs == NULL) { 49231f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 49241f6eb021SLiane Praza free((char *)ret->tes_fmri); 49251f6eb021SLiane Praza free((char *)ret->tes_prefix); 49261f6eb021SLiane Praza free(ret); 49271f6eb021SLiane Praza return (NULL); 49281f6eb021SLiane Praza } 49291f6eb021SLiane Praza ret->tes_errs_size = errs_size; 49301f6eb021SLiane Praza 49311f6eb021SLiane Praza return (ret); 49321f6eb021SLiane Praza } 49331f6eb021SLiane Praza 49341f6eb021SLiane Praza /* 49351f6eb021SLiane Praza * return 0 on success, if fails set scf_error() to: 49361f6eb021SLiane Praza * 49371f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 49381f6eb021SLiane Praza */ 49391f6eb021SLiane Praza int 49401f6eb021SLiane Praza _scf_tmpl_error_set_prefix(scf_tmpl_errors_t *errs, const char *prefix) 49411f6eb021SLiane Praza { 49421f6eb021SLiane Praza free((void *) errs->tes_prefix); 49431f6eb021SLiane Praza if (prefix == NULL) 49441f6eb021SLiane Praza errs->tes_prefix = strdup(""); 49451f6eb021SLiane Praza else 49461f6eb021SLiane Praza errs->tes_prefix = strdup(prefix); 49471f6eb021SLiane Praza if (errs->tes_prefix == NULL) { 49481f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 49491f6eb021SLiane Praza return (-1); 49501f6eb021SLiane Praza } 49511f6eb021SLiane Praza return (0); 49521f6eb021SLiane Praza } 49531f6eb021SLiane Praza 49541f6eb021SLiane Praza /* 49551f6eb021SLiane Praza * 49561f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 49571f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 49581f6eb021SLiane Praza */ 49591f6eb021SLiane Praza int 49601f6eb021SLiane Praza _scf_tmpl_add_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 49611f6eb021SLiane Praza const char *pg_name, const char *prop_name, 49621f6eb021SLiane Praza const char *ev1, const char *ev2, const char *actual, 49631f6eb021SLiane Praza const char *tmpl_fmri, const char *tmpl_pg_name, const char *tmpl_pg_type, 49641f6eb021SLiane Praza const char *tmpl_prop_name, const char *tmpl_prop_type) 49651f6eb021SLiane Praza { 49661f6eb021SLiane Praza scf_tmpl_error_t *err; 49671f6eb021SLiane Praza 49681f6eb021SLiane Praza assert(errs != NULL); 49691f6eb021SLiane Praza assert(tmpl_fmri != NULL); 49701f6eb021SLiane Praza 49711f6eb021SLiane Praza err = _create_error(errs); 49721f6eb021SLiane Praza if (err == NULL) 49731f6eb021SLiane Praza return (-1); 49741f6eb021SLiane Praza 49751f6eb021SLiane Praza err->te_type = type; 49761f6eb021SLiane Praza err->te_pg_name = pg_name; 49771f6eb021SLiane Praza err->te_prop_name = prop_name; 49781f6eb021SLiane Praza err->te_ev1 = ev1; 49791f6eb021SLiane Praza err->te_ev2 = ev2; 49801f6eb021SLiane Praza err->te_actual = actual; 49811f6eb021SLiane Praza err->te_tmpl_fmri = tmpl_fmri; 49821f6eb021SLiane Praza err->te_tmpl_pg_name = tmpl_pg_name; 49831f6eb021SLiane Praza err->te_tmpl_pg_type = tmpl_pg_type; 49841f6eb021SLiane Praza err->te_tmpl_prop_name = tmpl_prop_name; 49851f6eb021SLiane Praza err->te_tmpl_prop_type = tmpl_prop_type; 49861f6eb021SLiane Praza 49871f6eb021SLiane Praza return (0); 49881f6eb021SLiane Praza } 49891f6eb021SLiane Praza 49901f6eb021SLiane Praza /* 49911f6eb021SLiane Praza * returns an allocated string that must be freed with free() 49921f6eb021SLiane Praza * string contains converted 64-bit integer value 49931f6eb021SLiane Praza * flag set for signed values 49941f6eb021SLiane Praza * if fails return NULL and set scf_error() to: 49951f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 49961f6eb021SLiane Praza */ 49971f6eb021SLiane Praza static char * 49981f6eb021SLiane Praza _val_to_string(uint64_t val, int flag) 49991f6eb021SLiane Praza { 50001f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 50011f6eb021SLiane Praza char *buf; 50021f6eb021SLiane Praza 50031f6eb021SLiane Praza buf = malloc(sz); 50041f6eb021SLiane Praza if (buf == NULL) { 50051f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 50061f6eb021SLiane Praza return (NULL); 50071f6eb021SLiane Praza } 50081f6eb021SLiane Praza 50091f6eb021SLiane Praza if (flag == 0) 50101f6eb021SLiane Praza (void) snprintf(buf, sz, "%" PRIu64, val); 50111f6eb021SLiane Praza else 50121f6eb021SLiane Praza (void) snprintf(buf, sz, "%" PRIi64, (int64_t)val); 50131f6eb021SLiane Praza 50141f6eb021SLiane Praza return (buf); 50151f6eb021SLiane Praza } 50161f6eb021SLiane Praza 50171f6eb021SLiane Praza /* 50181f6eb021SLiane Praza * return 0 on success, -1 on failure. 50191f6eb021SLiane Praza * set scf_error() to: 50201f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 50211f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 50221f6eb021SLiane Praza * SCF_ERROR_DELETED 50231f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 50241f6eb021SLiane Praza * SCF_ERROR_INTERNAL 50251f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 50261f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 50271f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 50281f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 50291f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 50301f6eb021SLiane Praza */ 50311f6eb021SLiane Praza static int 50321f6eb021SLiane Praza _add_tmpl_missing_pg_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t) 50331f6eb021SLiane Praza { 50341f6eb021SLiane Praza char *ev1 = NULL; 50351f6eb021SLiane Praza char *ev2 = NULL; 50361f6eb021SLiane Praza char *t_fmri = NULL; 50371f6eb021SLiane Praza char *t_pg_name = NULL; 50381f6eb021SLiane Praza char *t_pg_type = NULL; 50391f6eb021SLiane Praza 50401f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL) 50411f6eb021SLiane Praza return (-1); 50421f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &t_pg_name) == -1) { 50431f6eb021SLiane Praza goto cleanup; 50441f6eb021SLiane Praza } 50451f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &t_pg_type) == -1) { 50461f6eb021SLiane Praza goto cleanup; 50471f6eb021SLiane Praza } 50481f6eb021SLiane Praza if ((ev1 = strdup(t_pg_name)) == NULL) { 50491f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 50501f6eb021SLiane Praza goto cleanup; 50511f6eb021SLiane Praza } 50521f6eb021SLiane Praza if ((ev2 = strdup(t_pg_type)) == NULL) { 50531f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 50541f6eb021SLiane Praza goto cleanup; 50551f6eb021SLiane Praza } 50561f6eb021SLiane Praza 50571f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PG, NULL, NULL, ev1, 50581f6eb021SLiane Praza ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL)); 50591f6eb021SLiane Praza cleanup: 50601f6eb021SLiane Praza free(ev1); 50611f6eb021SLiane Praza free(ev2); 50621f6eb021SLiane Praza free(t_fmri); 50631f6eb021SLiane Praza free(t_pg_name); 50641f6eb021SLiane Praza free(t_pg_type); 50651f6eb021SLiane Praza return (-1); 50661f6eb021SLiane Praza } 50671f6eb021SLiane Praza 50681f6eb021SLiane Praza /* 50691f6eb021SLiane Praza * return 0 on success, -1 on failure. 50701f6eb021SLiane Praza * set scf_error() to: 50711f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 50721f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 50731f6eb021SLiane Praza * SCF_ERROR_DELETED 50741f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 50751f6eb021SLiane Praza * SCF_ERROR_INTERNAL 50761f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 50771f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 50781f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 50791f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 50801f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 50811f6eb021SLiane Praza */ 50821f6eb021SLiane Praza static int 50831f6eb021SLiane Praza _add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t, 50841f6eb021SLiane Praza scf_propertygroup_t *pg) 50851f6eb021SLiane Praza { 50861f6eb021SLiane Praza char *pg_name = NULL; 50871f6eb021SLiane Praza char *ev1 = NULL; 50881f6eb021SLiane Praza char *actual = NULL; 50891f6eb021SLiane Praza char *t_fmri = NULL; 50901f6eb021SLiane Praza char *t_pg_name = NULL; 50911f6eb021SLiane Praza char *t_pg_type = NULL; 50921f6eb021SLiane Praza 50931f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL) 50941f6eb021SLiane Praza return (-1); 50951f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 50961f6eb021SLiane Praza goto cleanup; 50971f6eb021SLiane Praza if ((actual = _scf_get_pg_type(pg)) == NULL) 50981f6eb021SLiane Praza goto cleanup; 50991f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &t_pg_name) == -1) { 51001f6eb021SLiane Praza goto cleanup; 51011f6eb021SLiane Praza } 51021f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &t_pg_type) == -1) { 51031f6eb021SLiane Praza goto cleanup; 51041f6eb021SLiane Praza } 51051f6eb021SLiane Praza if ((ev1 = strdup(t_pg_type)) == NULL) { 51061f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 51071f6eb021SLiane Praza goto cleanup; 51081f6eb021SLiane Praza } 51091f6eb021SLiane Praza 51101f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PG_TYPE, pg_name, NULL, 51111f6eb021SLiane Praza ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type, NULL, NULL)); 51121f6eb021SLiane Praza cleanup: 51131f6eb021SLiane Praza free(pg_name); 51141f6eb021SLiane Praza free(ev1); 51151f6eb021SLiane Praza free(actual); 51161f6eb021SLiane Praza free(t_fmri); 51171f6eb021SLiane Praza free(t_pg_name); 51181f6eb021SLiane Praza free(t_pg_type); 51191f6eb021SLiane Praza return (-1); 51201f6eb021SLiane Praza } 51211f6eb021SLiane Praza 51221f6eb021SLiane Praza /* 51231f6eb021SLiane Praza * return 0 on success, -1 on failure. 51241f6eb021SLiane Praza * set scf_error() to: 51251f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 51261f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 51271f6eb021SLiane Praza * SCF_ERROR_DELETED 51281f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 51291f6eb021SLiane Praza * SCF_ERROR_INTERNAL 51301f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 51311f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 51321f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 51331f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 51341f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 51351f6eb021SLiane Praza */ 51361f6eb021SLiane Praza static int 51371f6eb021SLiane Praza _add_tmpl_missing_prop_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t, 51381f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt) 51391f6eb021SLiane Praza { 51401f6eb021SLiane Praza char *pg_name = NULL; 51411f6eb021SLiane Praza char *ev1 = NULL; 51421f6eb021SLiane Praza char *t_fmri = NULL; 51431f6eb021SLiane Praza char *t_pg_name = NULL; 51441f6eb021SLiane Praza char *t_pg_type = NULL; 51451f6eb021SLiane Praza char *t_prop_name = NULL; 51461f6eb021SLiane Praza char *t_prop_type = NULL; 51471f6eb021SLiane Praza 51481f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL) 51491f6eb021SLiane Praza return (-1); 51501f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 51511f6eb021SLiane Praza goto cleanup; 51521f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &t_pg_name) == -1) { 51531f6eb021SLiane Praza goto cleanup; 51541f6eb021SLiane Praza } 51551f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &t_pg_type) == -1) { 51561f6eb021SLiane Praza goto cleanup; 51571f6eb021SLiane Praza } 51581f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 51591f6eb021SLiane Praza goto cleanup; 51601f6eb021SLiane Praza } 51611f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 51621f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 51631f6eb021SLiane Praza free(t_prop_type); 51641f6eb021SLiane Praza t_prop_type = NULL; 51651f6eb021SLiane Praza } else if (t_prop_type == NULL) { 51661f6eb021SLiane Praza goto cleanup; 51671f6eb021SLiane Praza } 51681f6eb021SLiane Praza if (t_prop_type == NULL) 51691f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 51701f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 51711f6eb021SLiane Praza goto cleanup; 51721f6eb021SLiane Praza } 51731f6eb021SLiane Praza if ((ev1 = strdup(t_prop_name)) == NULL) { 51741f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 51751f6eb021SLiane Praza goto cleanup; 51761f6eb021SLiane Praza } 51771f6eb021SLiane Praza 51781f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PROP, pg_name, NULL, 51791f6eb021SLiane Praza ev1, NULL, NULL, t_fmri, t_pg_name, t_pg_type, t_prop_name, 51801f6eb021SLiane Praza t_prop_type)); 51811f6eb021SLiane Praza cleanup: 51821f6eb021SLiane Praza free(pg_name); 51831f6eb021SLiane Praza free(ev1); 51841f6eb021SLiane Praza free(t_fmri); 51851f6eb021SLiane Praza free(t_pg_name); 51861f6eb021SLiane Praza free(t_pg_type); 51871f6eb021SLiane Praza free(t_prop_name); 51881f6eb021SLiane Praza free(t_prop_type); 51891f6eb021SLiane Praza return (-1); 51901f6eb021SLiane Praza } 51911f6eb021SLiane Praza 51921f6eb021SLiane Praza /* 51931f6eb021SLiane Praza * return 0 on success, -1 on failure. 51941f6eb021SLiane Praza * set scf_error() to: 51951f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 51961f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 51971f6eb021SLiane Praza * SCF_ERROR_DELETED 51981f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 51991f6eb021SLiane Praza * SCF_ERROR_INTERNAL 52001f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 52011f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 52021f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 52031f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 52041f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 52051f6eb021SLiane Praza */ 52061f6eb021SLiane Praza static int 52071f6eb021SLiane Praza _add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t *errs, 52081f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop) 52091f6eb021SLiane Praza { 52101f6eb021SLiane Praza char *pg_name = NULL; 52111f6eb021SLiane Praza char *prop_name = NULL; 52121f6eb021SLiane Praza char *ev1 = NULL; 52131f6eb021SLiane Praza char *actual = NULL; 52141f6eb021SLiane Praza char *t_fmri = NULL; 52151f6eb021SLiane Praza char *t_pg_name = NULL; 52161f6eb021SLiane Praza char *t_pg_type = NULL; 52171f6eb021SLiane Praza char *t_prop_name = NULL; 52181f6eb021SLiane Praza char *t_prop_type = NULL; 52191f6eb021SLiane Praza 52201f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 52211f6eb021SLiane Praza return (-1); 52221f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 52231f6eb021SLiane Praza goto cleanup; 52241f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 52251f6eb021SLiane Praza goto cleanup; 52261f6eb021SLiane Praza if ((actual = _scf_get_prop_type(prop)) == NULL) 52271f6eb021SLiane Praza goto cleanup; 52281f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 52291f6eb021SLiane Praza goto cleanup; 52301f6eb021SLiane Praza } 52311f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 52321f6eb021SLiane Praza goto cleanup; 52331f6eb021SLiane Praza } 52341f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 52351f6eb021SLiane Praza goto cleanup; 52361f6eb021SLiane Praza } 52371f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 52381f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 52391f6eb021SLiane Praza free(t_prop_type); 52401f6eb021SLiane Praza t_prop_type = NULL; 52411f6eb021SLiane Praza } else if (t_prop_type == NULL) { 52421f6eb021SLiane Praza goto cleanup; 52431f6eb021SLiane Praza } 52441f6eb021SLiane Praza if (t_prop_type == NULL) 52451f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 52461f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 52471f6eb021SLiane Praza goto cleanup; 52481f6eb021SLiane Praza } 52491f6eb021SLiane Praza if ((ev1 = strdup(t_prop_type)) == NULL) { 52501f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 52511f6eb021SLiane Praza goto cleanup; 52521f6eb021SLiane Praza } 52531f6eb021SLiane Praza 52541f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PROP_TYPE, pg_name, 52551f6eb021SLiane Praza prop_name, ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type, 52561f6eb021SLiane Praza t_prop_name, t_prop_type)); 52571f6eb021SLiane Praza cleanup: 52581f6eb021SLiane Praza free(pg_name); 52591f6eb021SLiane Praza free(prop_name); 52601f6eb021SLiane Praza free(ev1); 52611f6eb021SLiane Praza free(actual); 52621f6eb021SLiane Praza free(t_fmri); 52631f6eb021SLiane Praza free(t_pg_name); 52641f6eb021SLiane Praza free(t_pg_type); 52651f6eb021SLiane Praza free(t_prop_name); 52661f6eb021SLiane Praza free(t_prop_type); 52671f6eb021SLiane Praza return (-1); 52681f6eb021SLiane Praza } 52691f6eb021SLiane Praza 52701f6eb021SLiane Praza /* 52711f6eb021SLiane Praza * return 0 on success, -1 on failure. 52721f6eb021SLiane Praza * set scf_error() to: 52731f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 52741f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 52751f6eb021SLiane Praza * SCF_ERROR_DELETED 52761f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 52771f6eb021SLiane Praza * SCF_ERROR_INTERNAL 52781f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 52791f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 52801f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 52811f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 52821f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 52831f6eb021SLiane Praza */ 52841f6eb021SLiane Praza static int 52851f6eb021SLiane Praza _add_tmpl_count_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 52861f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop, 52871f6eb021SLiane Praza uint64_t count, uint64_t *min, uint64_t *max) 52881f6eb021SLiane Praza { 52891f6eb021SLiane Praza char *pg_name = NULL; 52901f6eb021SLiane Praza char *prop_name = NULL; 52911f6eb021SLiane Praza char *s_min = NULL; 52921f6eb021SLiane Praza char *s_max = NULL; 52931f6eb021SLiane Praza char *num = NULL; 52941f6eb021SLiane Praza char *t_fmri = NULL; 52951f6eb021SLiane Praza char *t_pg_name = NULL; 52961f6eb021SLiane Praza char *t_pg_type = NULL; 52971f6eb021SLiane Praza char *t_prop_name = NULL; 52981f6eb021SLiane Praza char *t_prop_type = NULL; 52991f6eb021SLiane Praza 53001f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 53011f6eb021SLiane Praza return (-1); 53021f6eb021SLiane Praza switch (type) { 53031f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 53041f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 53051f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 53061f6eb021SLiane Praza goto cleanup; 53071f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 53081f6eb021SLiane Praza goto cleanup; 53091f6eb021SLiane Praza break; 53101f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 53111f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 53121f6eb021SLiane Praza break; 53131f6eb021SLiane Praza } 53141f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 53151f6eb021SLiane Praza goto cleanup; 53161f6eb021SLiane Praza } 53171f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 53181f6eb021SLiane Praza goto cleanup; 53191f6eb021SLiane Praza } 53201f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 53211f6eb021SLiane Praza goto cleanup; 53221f6eb021SLiane Praza } 53231f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 53241f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 53251f6eb021SLiane Praza free(t_prop_type); 53261f6eb021SLiane Praza t_prop_type = NULL; 53271f6eb021SLiane Praza } else if (t_prop_type == NULL) { 53281f6eb021SLiane Praza goto cleanup; 53291f6eb021SLiane Praza } 53301f6eb021SLiane Praza if (t_prop_type == NULL) 53311f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 53321f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 53331f6eb021SLiane Praza goto cleanup; 53341f6eb021SLiane Praza } 53351f6eb021SLiane Praza if (min == NULL) { 53361f6eb021SLiane Praza if ((s_min = strdup("")) == NULL) { 53371f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 53381f6eb021SLiane Praza goto cleanup; 53391f6eb021SLiane Praza } 53401f6eb021SLiane Praza } else { 53411f6eb021SLiane Praza if ((s_min = _val_to_string(*min, 0)) == NULL) { 53421f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 53431f6eb021SLiane Praza goto cleanup; 53441f6eb021SLiane Praza } 53451f6eb021SLiane Praza } 53461f6eb021SLiane Praza if (max == NULL) { 53471f6eb021SLiane Praza if ((s_max = strdup("")) == NULL) { 53481f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 53491f6eb021SLiane Praza goto cleanup; 53501f6eb021SLiane Praza } 53511f6eb021SLiane Praza } else { 53521f6eb021SLiane Praza if ((s_max = _val_to_string(*max, 0)) == NULL) { 53531f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 53541f6eb021SLiane Praza goto cleanup; 53551f6eb021SLiane Praza } 53561f6eb021SLiane Praza } 53571f6eb021SLiane Praza if ((num = _val_to_string(count, 0)) == NULL) { 53581f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 53591f6eb021SLiane Praza goto cleanup; 53601f6eb021SLiane Praza } 53611f6eb021SLiane Praza 53621f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min, 53631f6eb021SLiane Praza s_max, num, t_fmri, t_pg_name, t_pg_type, t_prop_name, 53641f6eb021SLiane Praza t_prop_type)); 53651f6eb021SLiane Praza cleanup: 53661f6eb021SLiane Praza free(pg_name); 53671f6eb021SLiane Praza free(prop_name); 53681f6eb021SLiane Praza free(s_min); 53691f6eb021SLiane Praza free(s_max); 53701f6eb021SLiane Praza free(num); 53711f6eb021SLiane Praza free(t_fmri); 53721f6eb021SLiane Praza free(t_pg_name); 53731f6eb021SLiane Praza free(t_pg_type); 53741f6eb021SLiane Praza free(t_prop_name); 53751f6eb021SLiane Praza free(t_prop_type); 53761f6eb021SLiane Praza return (-1); 53771f6eb021SLiane Praza } 53781f6eb021SLiane Praza 53791f6eb021SLiane Praza /* 53801f6eb021SLiane Praza * return 0 on success, -1 on failure. 53811f6eb021SLiane Praza * set scf_error() to: 53821f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 53831f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 53841f6eb021SLiane Praza * SCF_ERROR_DELETED 53851f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 53861f6eb021SLiane Praza * SCF_ERROR_INTERNAL 53871f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 53881f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 53891f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 53901f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 53911f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 53921f6eb021SLiane Praza */ 53931f6eb021SLiane Praza static int 53941f6eb021SLiane Praza _add_tmpl_constraint_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 53951f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop, 53961f6eb021SLiane Praza scf_value_t *val) 53971f6eb021SLiane Praza { 53981f6eb021SLiane Praza scf_type_t val_type; 53991f6eb021SLiane Praza char *pg_name = NULL; 54001f6eb021SLiane Praza char *prop_name = NULL; 54011f6eb021SLiane Praza char *value = NULL; 54021f6eb021SLiane Praza char *t_fmri = NULL; 54031f6eb021SLiane Praza char *t_pg_name = NULL; 54041f6eb021SLiane Praza char *t_pg_type = NULL; 54051f6eb021SLiane Praza char *t_prop_name = NULL; 54061f6eb021SLiane Praza char *t_prop_type = NULL; 54071f6eb021SLiane Praza 54081f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 54091f6eb021SLiane Praza return (-1); 54101f6eb021SLiane Praza switch (type) { 54111f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 54121f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 54131f6eb021SLiane Praza goto cleanup; 54141f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 54151f6eb021SLiane Praza goto cleanup; 54161f6eb021SLiane Praza /*FALLTHROUGH*/ 54171f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 54181f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 54191f6eb021SLiane Praza if ((value = _scf_value_get_as_string(val)) == NULL) 54201f6eb021SLiane Praza goto cleanup; 54211f6eb021SLiane Praza break; 54221f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 54231f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 54241f6eb021SLiane Praza /* use value for value type */ 54251f6eb021SLiane Praza val_type = scf_value_type(val); 54261f6eb021SLiane Praza if ((value = strdup(scf_type_to_string(val_type))) == 54271f6eb021SLiane Praza NULL) { 54281f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 54291f6eb021SLiane Praza goto cleanup; 54301f6eb021SLiane Praza } 54311f6eb021SLiane Praza break; 54321f6eb021SLiane Praza } 54331f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 54341f6eb021SLiane Praza goto cleanup; 54351f6eb021SLiane Praza } 54361f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 54371f6eb021SLiane Praza goto cleanup; 54381f6eb021SLiane Praza } 54391f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 54401f6eb021SLiane Praza goto cleanup; 54411f6eb021SLiane Praza } 54421f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 54431f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 54441f6eb021SLiane Praza free(t_prop_type); 54451f6eb021SLiane Praza t_prop_type = NULL; 54461f6eb021SLiane Praza } else if (t_prop_type == NULL) { 54471f6eb021SLiane Praza goto cleanup; 54481f6eb021SLiane Praza } 54491f6eb021SLiane Praza if (t_prop_type == NULL) 54501f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 54511f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 54521f6eb021SLiane Praza goto cleanup; 54531f6eb021SLiane Praza } 54541f6eb021SLiane Praza 54551f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, NULL, NULL, 54561f6eb021SLiane Praza value, t_fmri, t_pg_name, t_pg_type, t_prop_name, t_prop_type)); 54571f6eb021SLiane Praza cleanup: 54581f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 54591f6eb021SLiane Praza free(pg_name); 54601f6eb021SLiane Praza free(prop_name); 54611f6eb021SLiane Praza free(value); 54621f6eb021SLiane Praza free(t_fmri); 54631f6eb021SLiane Praza free(t_pg_name); 54641f6eb021SLiane Praza free(t_pg_type); 54651f6eb021SLiane Praza free(t_prop_name); 54661f6eb021SLiane Praza free(t_prop_type); 54671f6eb021SLiane Praza return (-1); 54681f6eb021SLiane Praza } 54691f6eb021SLiane Praza 54701f6eb021SLiane Praza /* 54711f6eb021SLiane Praza * return 0 on success, -1 on failure. 54721f6eb021SLiane Praza * set scf_error() to: 54731f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 54741f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 54751f6eb021SLiane Praza * SCF_ERROR_DELETED 54761f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 54771f6eb021SLiane Praza * SCF_ERROR_INTERNAL 54781f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 54791f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 54801f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 54811f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 54821f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 54831f6eb021SLiane Praza */ 54841f6eb021SLiane Praza static int 54851f6eb021SLiane Praza _add_tmpl_int_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 54861f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop, 54871f6eb021SLiane Praza int64_t val, int64_t *min, int64_t *max) 54881f6eb021SLiane Praza { 54891f6eb021SLiane Praza char *pg_name = NULL; 54901f6eb021SLiane Praza char *prop_name = NULL; 54911f6eb021SLiane Praza char *s_min = NULL; 54921f6eb021SLiane Praza char *s_max = NULL; 54931f6eb021SLiane Praza char *value = NULL; 54941f6eb021SLiane Praza char *t_fmri = NULL; 54951f6eb021SLiane Praza char *t_pg_name = NULL; 54961f6eb021SLiane Praza char *t_pg_type = NULL; 54971f6eb021SLiane Praza char *t_prop_name = NULL; 54981f6eb021SLiane Praza char *t_prop_type = NULL; 54991f6eb021SLiane Praza 55001f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 55011f6eb021SLiane Praza return (-1); 55021f6eb021SLiane Praza 55031f6eb021SLiane Praza switch (type) { 55041f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 55051f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 55061f6eb021SLiane Praza goto cleanup; 55071f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 55081f6eb021SLiane Praza goto cleanup; 55091f6eb021SLiane Praza break; 55101f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 55111f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 55121f6eb021SLiane Praza break; 55131f6eb021SLiane Praza } 55141f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 55151f6eb021SLiane Praza goto cleanup; 55161f6eb021SLiane Praza } 55171f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 55181f6eb021SLiane Praza goto cleanup; 55191f6eb021SLiane Praza } 55201f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 55211f6eb021SLiane Praza goto cleanup; 55221f6eb021SLiane Praza } 55231f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 55241f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 55251f6eb021SLiane Praza free(t_prop_type); 55261f6eb021SLiane Praza t_prop_type = NULL; 55271f6eb021SLiane Praza } else if (t_prop_type == NULL) { 55281f6eb021SLiane Praza goto cleanup; 55291f6eb021SLiane Praza } 55301f6eb021SLiane Praza if (t_prop_type == NULL) 55311f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 55321f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 55331f6eb021SLiane Praza goto cleanup; 55341f6eb021SLiane Praza } 55351f6eb021SLiane Praza if (min == NULL) { 55361f6eb021SLiane Praza if ((s_min = strdup("")) == NULL) { 55371f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 55381f6eb021SLiane Praza goto cleanup; 55391f6eb021SLiane Praza } 55401f6eb021SLiane Praza } else { 55411f6eb021SLiane Praza if ((s_min = _val_to_string(*((uint64_t *)min), 1)) == NULL) { 55421f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 55431f6eb021SLiane Praza goto cleanup; 55441f6eb021SLiane Praza } 55451f6eb021SLiane Praza } 55461f6eb021SLiane Praza if (max == NULL) { 55471f6eb021SLiane Praza if ((s_max = strdup("")) == NULL) { 55481f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 55491f6eb021SLiane Praza goto cleanup; 55501f6eb021SLiane Praza } 55511f6eb021SLiane Praza } else { 55521f6eb021SLiane Praza if ((s_max = _val_to_string(*((uint64_t *)max), 1)) == NULL) { 55531f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 55541f6eb021SLiane Praza goto cleanup; 55551f6eb021SLiane Praza } 55561f6eb021SLiane Praza } 55571f6eb021SLiane Praza if ((value = _val_to_string((uint64_t)val, 1)) == NULL) { 55581f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 55591f6eb021SLiane Praza goto cleanup; 55601f6eb021SLiane Praza } 55611f6eb021SLiane Praza 55621f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min, 55631f6eb021SLiane Praza s_max, value, t_fmri, t_pg_name, t_pg_type, t_prop_name, 55641f6eb021SLiane Praza t_prop_type)); 55651f6eb021SLiane Praza cleanup: 55661f6eb021SLiane Praza free(pg_name); 55671f6eb021SLiane Praza free(prop_name); 55681f6eb021SLiane Praza free(s_min); 55691f6eb021SLiane Praza free(s_max); 55701f6eb021SLiane Praza free(value); 55711f6eb021SLiane Praza free(t_fmri); 55721f6eb021SLiane Praza free(t_pg_name); 55731f6eb021SLiane Praza free(t_pg_type); 55741f6eb021SLiane Praza free(t_prop_name); 55751f6eb021SLiane Praza free(t_prop_type); 55761f6eb021SLiane Praza return (-1); 55771f6eb021SLiane Praza } 55781f6eb021SLiane Praza 55791f6eb021SLiane Praza /* 55801f6eb021SLiane Praza * return 0 on success, -1 on failure. 55811f6eb021SLiane Praza * set scf_error() to: 55821f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 55831f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 55841f6eb021SLiane Praza * SCF_ERROR_DELETED 55851f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 55861f6eb021SLiane Praza * SCF_ERROR_INTERNAL 55871f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 55881f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 55891f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 55901f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 55911f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 55921f6eb021SLiane Praza */ 55931f6eb021SLiane Praza static int 55941f6eb021SLiane Praza _add_tmpl_pg_redefine_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t, 55951f6eb021SLiane Praza scf_pg_tmpl_t *r) 55961f6eb021SLiane Praza { 55971f6eb021SLiane Praza char *ev1 = NULL; 55981f6eb021SLiane Praza char *ev2 = NULL; 55991f6eb021SLiane Praza char *t_fmri = NULL; 56001f6eb021SLiane Praza char *t_pg_name = NULL; 56011f6eb021SLiane Praza char *t_pg_type = NULL; 56021f6eb021SLiane Praza 56031f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(r)) == NULL) 56041f6eb021SLiane Praza return (-1); 56051f6eb021SLiane Praza if (scf_tmpl_pg_name(r, &t_pg_name) == -1) { 56061f6eb021SLiane Praza goto cleanup; 56071f6eb021SLiane Praza } 56081f6eb021SLiane Praza if (scf_tmpl_pg_type(r, &t_pg_type) == -1) { 56091f6eb021SLiane Praza goto cleanup; 56101f6eb021SLiane Praza } 56111f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &ev1) == -1) { 56121f6eb021SLiane Praza goto cleanup; 56131f6eb021SLiane Praza } 56141f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &ev2) == -1) { 56151f6eb021SLiane Praza goto cleanup; 56161f6eb021SLiane Praza } 56171f6eb021SLiane Praza 56181f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_PG_REDEFINE, NULL, NULL, 56191f6eb021SLiane Praza ev1, ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL)); 56201f6eb021SLiane Praza cleanup: 56211f6eb021SLiane Praza free(ev1); 56221f6eb021SLiane Praza free(ev2); 56231f6eb021SLiane Praza free(t_fmri); 56241f6eb021SLiane Praza free(t_pg_name); 56251f6eb021SLiane Praza free(t_pg_type); 56261f6eb021SLiane Praza return (-1); 56271f6eb021SLiane Praza } 56281f6eb021SLiane Praza 56291f6eb021SLiane Praza /* 56301f6eb021SLiane Praza * return 0 if value is within count ranges constraint. 56311f6eb021SLiane Praza * return -1 otherwise 56321f6eb021SLiane Praza */ 56331f6eb021SLiane Praza static int 56341f6eb021SLiane Praza _check_count_ranges(scf_count_ranges_t *cr, uint64_t v) 56351f6eb021SLiane Praza { 56361f6eb021SLiane Praza int i; 56371f6eb021SLiane Praza 56381f6eb021SLiane Praza for (i = 0; i < cr->scr_num_ranges; ++i) { 56391f6eb021SLiane Praza if (v >= cr->scr_min[i] && 56401f6eb021SLiane Praza v <= cr->scr_max[i]) { 56411f6eb021SLiane Praza /* value is within ranges constraint */ 56421f6eb021SLiane Praza return (0); 56431f6eb021SLiane Praza } 56441f6eb021SLiane Praza } 56451f6eb021SLiane Praza return (-1); 56461f6eb021SLiane Praza } 56471f6eb021SLiane Praza 56481f6eb021SLiane Praza /* 56491f6eb021SLiane Praza * return 0 if value is within count ranges constraint. 56501f6eb021SLiane Praza * return -1 otherwise 56511f6eb021SLiane Praza */ 56521f6eb021SLiane Praza static int 56531f6eb021SLiane Praza _check_int_ranges(scf_int_ranges_t *ir, int64_t v) 56541f6eb021SLiane Praza { 56551f6eb021SLiane Praza int i; 56561f6eb021SLiane Praza 56571f6eb021SLiane Praza for (i = 0; i < ir->sir_num_ranges; ++i) { 56581f6eb021SLiane Praza if (v >= ir->sir_min[i] && 56591f6eb021SLiane Praza v <= ir->sir_max[i]) { 56601f6eb021SLiane Praza /* value is within integer ranges constraint */ 56611f6eb021SLiane Praza return (0); 56621f6eb021SLiane Praza } 56631f6eb021SLiane Praza } 56641f6eb021SLiane Praza return (-1); 56651f6eb021SLiane Praza } 56661f6eb021SLiane Praza 56671f6eb021SLiane Praza /* 56681f6eb021SLiane Praza * int _value_in_constraint() 56691f6eb021SLiane Praza * 56701f6eb021SLiane Praza * Checks whether the supplied value violates any of the constraints 56711f6eb021SLiane Praza * specified in the supplied property template. If it does, an appropriate 56721f6eb021SLiane Praza * error is appended to "errs". pg and prop, if supplied, are used to 56731f6eb021SLiane Praza * augment the information in the error. Returns 0 on success. 56741f6eb021SLiane Praza * 56751f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 56761f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 56771f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 56781f6eb021SLiane Praza * SCF_ERROR_DELETED 56791f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 56801f6eb021SLiane Praza * SCF_ERROR_INTERNAL 56811f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 56821f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 56831f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 56841f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 56851f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 56861f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 56871f6eb021SLiane Praza */ 56881f6eb021SLiane Praza static int 56891f6eb021SLiane Praza _value_in_constraint(scf_propertygroup_t *pg, scf_property_t *prop, 56901f6eb021SLiane Praza const scf_prop_tmpl_t *pt, scf_value_t *value, scf_tmpl_errors_t *errs) 56911f6eb021SLiane Praza { 56921f6eb021SLiane Praza scf_type_t type, tmpl_type; 56931f6eb021SLiane Praza scf_values_t vals; 56941f6eb021SLiane Praza scf_tmpl_error_type_t terr_type; 56951f6eb021SLiane Praza uint64_t v_count; 56961f6eb021SLiane Praza int64_t v_int; 56971f6eb021SLiane Praza char *vstr; 56981f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 56991f6eb021SLiane Praza ssize_t ret = 0; 57001f6eb021SLiane Praza char **constraints; 57011f6eb021SLiane Praza int n = 0; 57021f6eb021SLiane Praza int r; 57031f6eb021SLiane Praza int err_flag = 0; 57041f6eb021SLiane Praza scf_count_ranges_t cr; 57051f6eb021SLiane Praza scf_int_ranges_t ir; 57061f6eb021SLiane Praza 57071f6eb021SLiane Praza type = scf_value_type(value); 57081f6eb021SLiane Praza if (type == SCF_TYPE_INVALID) { 57091f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 57101f6eb021SLiane Praza return (-1); 57111f6eb021SLiane Praza } 57121f6eb021SLiane Praza 57131f6eb021SLiane Praza /* Check if template type matches value type. */ 57141f6eb021SLiane Praza if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) { 57151f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) 57161f6eb021SLiane Praza /* type is not wildcarded */ 57171f6eb021SLiane Praza return (-1); 57181f6eb021SLiane Praza } else if (tmpl_type != type) { 57191f6eb021SLiane Praza if (errs != NULL) { 57201f6eb021SLiane Praza if (pg == NULL && prop == NULL) { 57211f6eb021SLiane Praza if (_add_tmpl_constraint_error(errs, 57221f6eb021SLiane Praza SCF_TERR_PROP_TYPE_MISMATCH, NULL, pt, 57231f6eb021SLiane Praza NULL, value) == -1) 57241f6eb021SLiane Praza return (-1); 57251f6eb021SLiane Praza } 57261f6eb021SLiane Praza } 57271f6eb021SLiane Praza return (1); 57281f6eb021SLiane Praza } 57291f6eb021SLiane Praza 57301f6eb021SLiane Praza /* Numeric values should be checked against any range constraints. */ 57311f6eb021SLiane Praza switch (type) { 57321f6eb021SLiane Praza case SCF_TYPE_COUNT: 57331f6eb021SLiane Praza r = scf_value_get_count(value, &v_count); 57341f6eb021SLiane Praza assert(r == 0); 57351f6eb021SLiane Praza 57361f6eb021SLiane Praza if (scf_tmpl_value_count_range_constraints(pt, &cr) != 0) { 57371f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 57381f6eb021SLiane Praza break; 57391f6eb021SLiane Praza if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) 57401f6eb021SLiane Praza (void) scf_set_error( 57411f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 57421f6eb021SLiane Praza return (-1); 57431f6eb021SLiane Praza } else { 57441f6eb021SLiane Praza if (_check_count_ranges(&cr, v_count) == 0) { 57451f6eb021SLiane Praza /* value is within ranges constraint */ 57461f6eb021SLiane Praza scf_count_ranges_destroy(&cr); 57471f6eb021SLiane Praza return (0); 57481f6eb021SLiane Praza } 57491f6eb021SLiane Praza scf_count_ranges_destroy(&cr); 57501f6eb021SLiane Praza } 57511f6eb021SLiane Praza 57521f6eb021SLiane Praza /* 57531f6eb021SLiane Praza * If we get here, we have a possible constraint 57541f6eb021SLiane Praza * violation. 57551f6eb021SLiane Praza */ 57561f6eb021SLiane Praza err_flag |= 0x1; /* RANGE_VIOLATION, count */ 57571f6eb021SLiane Praza break; 57581f6eb021SLiane Praza case SCF_TYPE_INTEGER: 57591f6eb021SLiane Praza if (scf_value_get_integer(value, &v_int) != 0) 57601f6eb021SLiane Praza assert(0); 57611f6eb021SLiane Praza if (scf_tmpl_value_int_range_constraints(pt, &ir) != 0) { 57621f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 57631f6eb021SLiane Praza break; 57641f6eb021SLiane Praza if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED) 57651f6eb021SLiane Praza (void) scf_set_error( 57661f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 57671f6eb021SLiane Praza return (-1); 57681f6eb021SLiane Praza } else { 57691f6eb021SLiane Praza if (_check_int_ranges(&ir, v_int) == 0) { 57701f6eb021SLiane Praza /* value is within ranges constraint */ 57711f6eb021SLiane Praza scf_int_ranges_destroy(&ir); 57721f6eb021SLiane Praza return (0); 57731f6eb021SLiane Praza } 57741f6eb021SLiane Praza scf_int_ranges_destroy(&ir); 57751f6eb021SLiane Praza } 57761f6eb021SLiane Praza /* 57771f6eb021SLiane Praza * If we get here, we have a possible constraint 57781f6eb021SLiane Praza * violation. 57791f6eb021SLiane Praza */ 57801f6eb021SLiane Praza err_flag |= 0x2; /* RANGE_VIOLATION, integer */ 57811f6eb021SLiane Praza break; 57821f6eb021SLiane Praza default: 57831f6eb021SLiane Praza break; 57841f6eb021SLiane Praza } 57851f6eb021SLiane Praza 57861f6eb021SLiane Praza vstr = malloc(sz); 57871f6eb021SLiane Praza if (vstr == NULL) { 57881f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 57891f6eb021SLiane Praza return (-1); 57901f6eb021SLiane Praza } 57911f6eb021SLiane Praza 57921f6eb021SLiane Praza /* 57931f6eb021SLiane Praza * If a set of names is provided, confirm value has one of 57941f6eb021SLiane Praza * those names. 57951f6eb021SLiane Praza */ 57961f6eb021SLiane Praza if (scf_tmpl_value_name_constraints(pt, &vals) != 0) { 57971f6eb021SLiane Praza free(vstr); 57981f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) { 57991f6eb021SLiane Praza return (-1); 58001f6eb021SLiane Praza } 58011f6eb021SLiane Praza } else { 58021f6eb021SLiane Praza r = scf_value_get_as_string_typed(value, type, vstr, sz); 58031f6eb021SLiane Praza 58041f6eb021SLiane Praza /* 58051f6eb021SLiane Praza * All errors (INVALID_ARGUMENT, NOT_SET, TYPE_MISMATCH) 58061f6eb021SLiane Praza * should be impossible or already caught above. 58071f6eb021SLiane Praza */ 58081f6eb021SLiane Praza assert(r > 0); 58091f6eb021SLiane Praza 58101f6eb021SLiane Praza constraints = vals.values.v_astring; 58111f6eb021SLiane Praza for (n = 0; constraints[n] != NULL; ++n) { 58121f6eb021SLiane Praza if (strcmp(constraints[n], vstr) == 0) { 58131f6eb021SLiane Praza /* value is within constraint */ 58141f6eb021SLiane Praza scf_values_destroy(&vals); 58151f6eb021SLiane Praza free(vstr); 58161f6eb021SLiane Praza return (0); 58171f6eb021SLiane Praza } 58181f6eb021SLiane Praza } 58191f6eb021SLiane Praza /* if we get here, we have a constraint violation */ 58201f6eb021SLiane Praza err_flag |= 0x4; /* CONSTRAINT_VIOLATED */ 58211f6eb021SLiane Praza scf_values_destroy(&vals); 58221f6eb021SLiane Praza free(vstr); 58231f6eb021SLiane Praza } 58241f6eb021SLiane Praza if (err_flag != 0) 58251f6eb021SLiane Praza ret = 1; 58261f6eb021SLiane Praza /* register the errors found */ 58271f6eb021SLiane Praza if (ret == 1 && errs != NULL) { 58281f6eb021SLiane Praza if ((err_flag & 0x1) == 0x1) { 58291f6eb021SLiane Praza /* 58301f6eb021SLiane Praza * Help make the error more human-friendly. If 58311f6eb021SLiane Praza * pg and prop are provided, we know we're 58321f6eb021SLiane Praza * validating repository data. If they're not, 58331f6eb021SLiane Praza * we're validating a potentially hypothetical 58341f6eb021SLiane Praza * value. 58351f6eb021SLiane Praza */ 58361f6eb021SLiane Praza if (pg == NULL && prop == NULL) 58371f6eb021SLiane Praza terr_type = SCF_TERR_VALUE_OUT_OF_RANGE; 58381f6eb021SLiane Praza else 58391f6eb021SLiane Praza terr_type = SCF_TERR_RANGE_VIOLATION; 58401f6eb021SLiane Praza if (_add_tmpl_count_error(errs, terr_type, pg, pt, 58411f6eb021SLiane Praza prop, v_count, 0, 0) == -1) 58421f6eb021SLiane Praza ret = -1; 58431f6eb021SLiane Praza } 58441f6eb021SLiane Praza if ((err_flag & 0x2) == 0x2) { 58451f6eb021SLiane Praza if (pg == NULL && prop == NULL) 58461f6eb021SLiane Praza terr_type = SCF_TERR_VALUE_OUT_OF_RANGE; 58471f6eb021SLiane Praza else 58481f6eb021SLiane Praza terr_type = SCF_TERR_RANGE_VIOLATION; 58491f6eb021SLiane Praza if (_add_tmpl_int_error(errs, terr_type, pg, pt, prop, 58501f6eb021SLiane Praza v_int, 0, 0) == -1) 58511f6eb021SLiane Praza ret = -1; 58521f6eb021SLiane Praza } 58531f6eb021SLiane Praza if ((err_flag & 0x4) == 0x4) { 58541f6eb021SLiane Praza if (pg == NULL && prop == NULL) 58551f6eb021SLiane Praza terr_type = SCF_TERR_INVALID_VALUE; 58561f6eb021SLiane Praza else 58571f6eb021SLiane Praza terr_type = SCF_TERR_VALUE_CONSTRAINT_VIOLATED; 58581f6eb021SLiane Praza if (_add_tmpl_constraint_error(errs, terr_type, pg, 58591f6eb021SLiane Praza pt, prop, value) == -1) 58601f6eb021SLiane Praza ret = -1; 58611f6eb021SLiane Praza } 58621f6eb021SLiane Praza } 58631f6eb021SLiane Praza return (ret); 58641f6eb021SLiane Praza } 58651f6eb021SLiane Praza 58661f6eb021SLiane Praza /* 58671f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 58681f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 58691f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 58701f6eb021SLiane Praza * SCF_ERROR_DELETED 58711f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 58721f6eb021SLiane Praza * SCF_ERROR_INTERNAL 58731f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 58741f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 58751f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 58761f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 58771f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 58781f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 58791f6eb021SLiane Praza */ 58801f6eb021SLiane Praza int 58811f6eb021SLiane Praza scf_tmpl_value_in_constraint(const scf_prop_tmpl_t *pt, scf_value_t *value, 58821f6eb021SLiane Praza scf_tmpl_errors_t **errs) 58831f6eb021SLiane Praza { 58841f6eb021SLiane Praza scf_tmpl_errors_t *e = NULL; 58851f6eb021SLiane Praza 58861f6eb021SLiane Praza if (errs != NULL) { 58871f6eb021SLiane Praza char *fmri; 58881f6eb021SLiane Praza 58891f6eb021SLiane Praza if ((fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 58901f6eb021SLiane Praza return (-1); 58911f6eb021SLiane Praza *errs = _scf_create_errors(fmri, 1); 58921f6eb021SLiane Praza free(fmri); 58931f6eb021SLiane Praza if (*errs == NULL) 58941f6eb021SLiane Praza return (-1); 58951f6eb021SLiane Praza e = *errs; 58961f6eb021SLiane Praza } 58971f6eb021SLiane Praza 58981f6eb021SLiane Praza return (_value_in_constraint(NULL, NULL, pt, value, e)); 58991f6eb021SLiane Praza } 59001f6eb021SLiane Praza 59011f6eb021SLiane Praza scf_tmpl_error_t * 59021f6eb021SLiane Praza scf_tmpl_next_error(scf_tmpl_errors_t *errs) 59031f6eb021SLiane Praza { 59041f6eb021SLiane Praza if (errs->tes_index < errs->tes_num_errs) { 59051f6eb021SLiane Praza assert(errs->tes_errs[errs->tes_index] != NULL); 59061f6eb021SLiane Praza return (errs->tes_errs[errs->tes_index++]); 59071f6eb021SLiane Praza } else { 59081f6eb021SLiane Praza return (NULL); 59091f6eb021SLiane Praza } 59101f6eb021SLiane Praza } 59111f6eb021SLiane Praza 59121f6eb021SLiane Praza void 59131f6eb021SLiane Praza scf_tmpl_reset_errors(scf_tmpl_errors_t *errs) 59141f6eb021SLiane Praza { 59151f6eb021SLiane Praza errs->tes_index = 0; 59161f6eb021SLiane Praza } 59171f6eb021SLiane Praza 59181f6eb021SLiane Praza int 59191f6eb021SLiane Praza scf_tmpl_strerror(scf_tmpl_error_t *err, char *s, size_t n, int flag) 59201f6eb021SLiane Praza { 59211f6eb021SLiane Praza const char *str; 59221f6eb021SLiane Praza int i; 59231f6eb021SLiane Praza int ret = -1; 59241f6eb021SLiane Praza int nsz = 0; /* err msg length */ 59251f6eb021SLiane Praza int sz = n; /* available buffer size */ 59261f6eb021SLiane Praza char *buf = s; /* where to append in buffer */ 59271f6eb021SLiane Praza char *s0 = (flag == SCF_TMPL_STRERROR_HUMAN) ? ":\n\t" : ": "; 59281f6eb021SLiane Praza char *s1 = (flag == SCF_TMPL_STRERROR_HUMAN) ? "\n\t" : "; "; 59291f6eb021SLiane Praza char *sep = s0; 59301f6eb021SLiane Praza const char *val; 59311f6eb021SLiane Praza 59321f6eb021SLiane Praza /* prefix */ 59331f6eb021SLiane Praza if (err->te_errs->tes_prefix != NULL) { 59341f6eb021SLiane Praza ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN, 59351f6eb021SLiane Praza err->te_errs->tes_prefix)); 59361f6eb021SLiane Praza nsz += ret; 59371f6eb021SLiane Praza sz = (sz - ret) > 0 ? sz - ret : 0; 59381f6eb021SLiane Praza buf = (sz > 0) ? s + nsz : NULL; 59391f6eb021SLiane Praza } 59401f6eb021SLiane Praza /* error message */ 59411f6eb021SLiane Praza ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN, 59421f6eb021SLiane Praza em_desc[err->te_type].em_msg)); 59431f6eb021SLiane Praza nsz += ret; 59441f6eb021SLiane Praza sz = (sz - ret) > 0 ? sz - ret : 0; 59451f6eb021SLiane Praza buf = (sz > 0) ? s + nsz : NULL; 59461f6eb021SLiane Praza 59471f6eb021SLiane Praza for (i = 0; _tmpl_error_items[i].get_desc != NULL; ++i) { 59481f6eb021SLiane Praza if ((str = _tmpl_error_items[i].get_desc(err)) == NULL) 59491f6eb021SLiane Praza /* no item to print */ 59501f6eb021SLiane Praza continue; 59511f6eb021SLiane Praza val = _tmpl_error_items[i].get_val(err); 59521f6eb021SLiane Praza ret = snprintf(buf, sz, "%s%s=\"%s\"", sep, str, 59531f6eb021SLiane Praza (val == NULL) ? "" : val); 59541f6eb021SLiane Praza nsz += ret; 59551f6eb021SLiane Praza sz = (sz - ret) > 0 ? sz - ret : 0; 59561f6eb021SLiane Praza buf = (sz > 0) ? s + nsz : NULL; 59571f6eb021SLiane Praza sep = s1; 59581f6eb021SLiane Praza } 59591f6eb021SLiane Praza return (nsz); 59601f6eb021SLiane Praza } 59611f6eb021SLiane Praza 59621f6eb021SLiane Praza /* 59631f6eb021SLiane Praza * return 0 on success, -1 on failure. 59641f6eb021SLiane Praza * set scf_error() to: 59651f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 59661f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 59671f6eb021SLiane Praza * SCF_ERROR_DELETED 59681f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 59691f6eb021SLiane Praza * SCF_ERROR_INTERNAL 59701f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 59711f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 59721f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 59731f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 59741f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 59751f6eb021SLiane Praza */ 59761f6eb021SLiane Praza static int 59771f6eb021SLiane Praza _validate_cardinality(scf_propertygroup_t *pg, scf_prop_tmpl_t *pt, 59781f6eb021SLiane Praza scf_property_t *prop, scf_tmpl_errors_t *errs) 59791f6eb021SLiane Praza { 59801f6eb021SLiane Praza uint64_t min, max; 59811f6eb021SLiane Praza scf_handle_t *h; 59821f6eb021SLiane Praza scf_iter_t *iter = NULL; 59831f6eb021SLiane Praza scf_value_t *val = NULL; 59841f6eb021SLiane Praza int count = 0; 59851f6eb021SLiane Praza int ret = -1; 59861f6eb021SLiane Praza int r; 59871f6eb021SLiane Praza 59881f6eb021SLiane Praza if (scf_tmpl_prop_cardinality(pt, &min, &max) != 0) { 59891f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 59901f6eb021SLiane Praza return (0); 59911f6eb021SLiane Praza else 59921f6eb021SLiane Praza return (-1); 59931f6eb021SLiane Praza } 59941f6eb021SLiane Praza 59951f6eb021SLiane Praza /* Any number of values permitted. Just return success. */ 59961f6eb021SLiane Praza if (min == 0 && max == UINT64_MAX) { 59971f6eb021SLiane Praza return (0); 59981f6eb021SLiane Praza } 59991f6eb021SLiane Praza 60001f6eb021SLiane Praza h = scf_property_handle(prop); 60011f6eb021SLiane Praza if (h == NULL) { 60021f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 60031f6eb021SLiane Praza goto cleanup; 60041f6eb021SLiane Praza } 60051f6eb021SLiane Praza 60061f6eb021SLiane Praza iter = scf_iter_create(h); 60071f6eb021SLiane Praza val = scf_value_create(h); 60081f6eb021SLiane Praza if (iter == NULL || val == NULL) { 60091f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 60101f6eb021SLiane Praza goto cleanup; 60111f6eb021SLiane Praza } else { 60121f6eb021SLiane Praza assert(0); 60131f6eb021SLiane Praza abort(); 60141f6eb021SLiane Praza } 60151f6eb021SLiane Praza } 60161f6eb021SLiane Praza 60171f6eb021SLiane Praza if (scf_iter_property_values(iter, prop) != 0) { 60181f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 60191f6eb021SLiane Praza goto cleanup; 60201f6eb021SLiane Praza } else { 60211f6eb021SLiane Praza assert(0); 60221f6eb021SLiane Praza abort(); 60231f6eb021SLiane Praza } 60241f6eb021SLiane Praza } 60251f6eb021SLiane Praza 60261f6eb021SLiane Praza while ((r = scf_iter_next_value(iter, val)) == 1) 60271f6eb021SLiane Praza count++; 60281f6eb021SLiane Praza 60291f6eb021SLiane Praza if (r < 0) { 60301f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 60311f6eb021SLiane Praza goto cleanup; 60321f6eb021SLiane Praza } else { 60331f6eb021SLiane Praza assert(0); 60341f6eb021SLiane Praza abort(); 60351f6eb021SLiane Praza } 60361f6eb021SLiane Praza } 60371f6eb021SLiane Praza 60381f6eb021SLiane Praza if (count < min || count > max) 60391f6eb021SLiane Praza if (_add_tmpl_count_error(errs, SCF_TERR_CARDINALITY_VIOLATION, 60401f6eb021SLiane Praza pg, pt, prop, (uint64_t)count, &min, &max) == -1) 60411f6eb021SLiane Praza goto cleanup; 60421f6eb021SLiane Praza 60431f6eb021SLiane Praza ret = 0; 60441f6eb021SLiane Praza 60451f6eb021SLiane Praza cleanup: 60461f6eb021SLiane Praza scf_iter_destroy(iter); 60471f6eb021SLiane Praza scf_value_destroy(val); 60481f6eb021SLiane Praza return (ret); 60491f6eb021SLiane Praza } 60501f6eb021SLiane Praza 60511f6eb021SLiane Praza /* 60521f6eb021SLiane Praza * Returns -1 on error. Sets scf_error(): 60531f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 60541f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 60551f6eb021SLiane Praza * SCF_ERROR_DELETED 60561f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 60571f6eb021SLiane Praza * SCF_ERROR_INTERNAL 60581f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 60591f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 60601f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 60611f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 60621f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 60631f6eb021SLiane Praza */ 60641f6eb021SLiane Praza static int 60651f6eb021SLiane Praza _check_property(scf_prop_tmpl_t *pt, scf_propertygroup_t *pg, 60661f6eb021SLiane Praza scf_property_t *prop, scf_tmpl_errors_t *errs) 60671f6eb021SLiane Praza { 60681f6eb021SLiane Praza scf_type_t tmpl_type; 60691f6eb021SLiane Praza uint8_t required; 60701f6eb021SLiane Praza scf_handle_t *h; 60711f6eb021SLiane Praza scf_iter_t *iter = NULL; 60721f6eb021SLiane Praza scf_value_t *val = NULL; 60731f6eb021SLiane Praza int r; 60741f6eb021SLiane Praza int ret = -1; 60751f6eb021SLiane Praza 60761f6eb021SLiane Praza h = scf_pg_handle(pg); 60771f6eb021SLiane Praza if (h == NULL) { 60781f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 60791f6eb021SLiane Praza return (-1); 60801f6eb021SLiane Praza } 60811f6eb021SLiane Praza 60821f6eb021SLiane Praza iter = scf_iter_create(h); 60831f6eb021SLiane Praza val = scf_value_create(h); 60841f6eb021SLiane Praza if (iter == NULL || val == NULL) { 60851f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 60861f6eb021SLiane Praza scf_iter_destroy(iter); 60871f6eb021SLiane Praza scf_value_destroy(val); 60881f6eb021SLiane Praza return (-1); 60891f6eb021SLiane Praza } else { 60901f6eb021SLiane Praza assert(0); 60911f6eb021SLiane Praza abort(); 60921f6eb021SLiane Praza } 60931f6eb021SLiane Praza } 60941f6eb021SLiane Praza 60951f6eb021SLiane Praza if (scf_tmpl_prop_required(pt, &required) != 0) 60961f6eb021SLiane Praza goto cleanup; 60971f6eb021SLiane Praza 60981f6eb021SLiane Praza /* Check type */ 60991f6eb021SLiane Praza if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) { 61001f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) { 61011f6eb021SLiane Praza goto cleanup; 61021f6eb021SLiane Praza } else if (required) { 61031f6eb021SLiane Praza /* If required, type must be specified. */ 61041f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 61051f6eb021SLiane Praza goto cleanup; 61061f6eb021SLiane Praza } 61071f6eb021SLiane Praza } else if (scf_property_is_type(prop, tmpl_type) != 0) { 61081f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 61091f6eb021SLiane Praza goto cleanup; 61101f6eb021SLiane Praza } else switch (scf_error()) { 61111f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 61121f6eb021SLiane Praza if (_add_tmpl_wrong_prop_type_error(errs, pg, pt, 61131f6eb021SLiane Praza prop) == -1) 61141f6eb021SLiane Praza goto cleanup; 61151f6eb021SLiane Praza break; 61161f6eb021SLiane Praza 61171f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 61181f6eb021SLiane Praza /* 61191f6eb021SLiane Praza * tmpl_prop_type shouldn't have handed back 61201f6eb021SLiane Praza * an invalid property type. 61211f6eb021SLiane Praza */ 61221f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 61231f6eb021SLiane Praza default: 61241f6eb021SLiane Praza assert(0); 61251f6eb021SLiane Praza abort(); 61261f6eb021SLiane Praza } 61271f6eb021SLiane Praza } 61281f6eb021SLiane Praza 61291f6eb021SLiane Praza 61301f6eb021SLiane Praza /* Cardinality */ 61311f6eb021SLiane Praza if (_validate_cardinality(pg, pt, prop, errs) == -1) 61321f6eb021SLiane Praza goto cleanup; 61331f6eb021SLiane Praza 61341f6eb021SLiane Praza /* Value constraints */ 61351f6eb021SLiane Praza /* 61361f6eb021SLiane Praza * Iterate through each value, and confirm it is defined as 61371f6eb021SLiane Praza * constrained. 61381f6eb021SLiane Praza */ 61391f6eb021SLiane Praza if (scf_iter_property_values(iter, prop) != 0) { 61401f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET && 61411f6eb021SLiane Praza scf_error() != SCF_ERROR_HANDLE_MISMATCH); 61421f6eb021SLiane Praza goto cleanup; 61431f6eb021SLiane Praza } 61441f6eb021SLiane Praza 61451f6eb021SLiane Praza while ((r = scf_iter_next_value(iter, val)) == 1) { 61461f6eb021SLiane Praza if (_value_in_constraint(pg, prop, pt, val, errs) == -1) { 61471f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 61481f6eb021SLiane Praza goto cleanup; 61491f6eb021SLiane Praza } else switch (scf_error()) { 61501f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 61511f6eb021SLiane Praza goto cleanup; 61521f6eb021SLiane Praza 61531f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 61541f6eb021SLiane Praza default: 61551f6eb021SLiane Praza assert(0); 61561f6eb021SLiane Praza abort(); 61571f6eb021SLiane Praza } 61581f6eb021SLiane Praza } 61591f6eb021SLiane Praza } 61601f6eb021SLiane Praza 61611f6eb021SLiane Praza if (r < 0) { 61621f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 61631f6eb021SLiane Praza goto cleanup; 61641f6eb021SLiane Praza } else { 61651f6eb021SLiane Praza assert(0); 61661f6eb021SLiane Praza abort(); 61671f6eb021SLiane Praza } 61681f6eb021SLiane Praza } 61691f6eb021SLiane Praza 61701f6eb021SLiane Praza ret = 0; 61711f6eb021SLiane Praza 61721f6eb021SLiane Praza cleanup: 61731f6eb021SLiane Praza scf_iter_destroy(iter); 61741f6eb021SLiane Praza scf_value_destroy(val); 61751f6eb021SLiane Praza return (ret); 61761f6eb021SLiane Praza } 61771f6eb021SLiane Praza 61781f6eb021SLiane Praza /* 61791f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 61801f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 61811f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 61821f6eb021SLiane Praza * SCF_ERROR_DELETED 61831f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 61841f6eb021SLiane Praza * SCF_ERROR_INTERNAL 61851f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 61861f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 61871f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 61881f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 61891f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 61901f6eb021SLiane Praza */ 61911f6eb021SLiane Praza static int 61921f6eb021SLiane Praza _check_pg(scf_pg_tmpl_t *t, scf_propertygroup_t *pg, char *pg_name, 61931f6eb021SLiane Praza char *type, scf_tmpl_errors_t *errs) 61941f6eb021SLiane Praza { 61951f6eb021SLiane Praza scf_prop_tmpl_t *pt = NULL; 61961f6eb021SLiane Praza char *pg_type = NULL; 61971f6eb021SLiane Praza scf_iter_t *iter = NULL; 61981f6eb021SLiane Praza uint8_t pg_required; 61991f6eb021SLiane Praza scf_property_t *prop = NULL; 62001f6eb021SLiane Praza scf_handle_t *h; 62011f6eb021SLiane Praza int r; 62021f6eb021SLiane Praza char *prop_name = NULL; 62031f6eb021SLiane Praza ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 62041f6eb021SLiane Praza int ret = -1; 62051f6eb021SLiane Praza 62061f6eb021SLiane Praza assert(pg_name != NULL); 62071f6eb021SLiane Praza assert(t != NULL); 62081f6eb021SLiane Praza assert(pg != NULL); 62091f6eb021SLiane Praza assert(type != NULL); 62101f6eb021SLiane Praza assert(nsize != 0); 62111f6eb021SLiane Praza 62121f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) { 62131f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 62141f6eb021SLiane Praza return (-1); 62151f6eb021SLiane Praza } 62161f6eb021SLiane Praza if ((pt = scf_tmpl_prop_create(h)) == NULL) { 62171f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 62181f6eb021SLiane Praza return (-1); 62191f6eb021SLiane Praza } 62201f6eb021SLiane Praza 62211f6eb021SLiane Praza if ((prop = scf_property_create(h)) == NULL) { 62221f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 62231f6eb021SLiane Praza goto cleanup; 62241f6eb021SLiane Praza } 62251f6eb021SLiane Praza 62261f6eb021SLiane Praza if ((iter = scf_iter_create(h)) == NULL) { 62271f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 62281f6eb021SLiane Praza goto cleanup; 62291f6eb021SLiane Praza } 62301f6eb021SLiane Praza if ((prop_name = malloc(nsize)) == NULL) { 62311f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 62321f6eb021SLiane Praza goto cleanup; 62331f6eb021SLiane Praza } 62341f6eb021SLiane Praza 62351f6eb021SLiane Praza if (scf_tmpl_pg_required(t, &pg_required) != 0) 62361f6eb021SLiane Praza goto cleanup; 62371f6eb021SLiane Praza 62381f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &pg_type) == -1) { 62391f6eb021SLiane Praza goto cleanup; 62401f6eb021SLiane Praza } else if (pg_required != 0 && 62411f6eb021SLiane Praza strcmp(SCF_TMPL_WILDCARD, pg_type) == 0) { 62421f6eb021SLiane Praza /* Type must be specified for required pgs. */ 62431f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 62441f6eb021SLiane Praza goto cleanup; 62451f6eb021SLiane Praza } 62461f6eb021SLiane Praza 62471f6eb021SLiane Praza if (pg_type != NULL) { 62481f6eb021SLiane Praza if (strcmp(pg_type, type) != 0 && 62491f6eb021SLiane Praza strcmp(pg_type, SCF_TMPL_WILDCARD) != 0) { 62501f6eb021SLiane Praza if (_add_tmpl_wrong_pg_type_error(errs, t, pg) == -1) 62511f6eb021SLiane Praza goto cleanup; 62521f6eb021SLiane Praza } 62531f6eb021SLiane Praza } 62541f6eb021SLiane Praza 62551f6eb021SLiane Praza 62561f6eb021SLiane Praza /* Iterate through properties in the repository and check them. */ 62571f6eb021SLiane Praza if (scf_iter_pg_properties(iter, pg) != 0) { 62581f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 62591f6eb021SLiane Praza goto cleanup; 62601f6eb021SLiane Praza } else { 62611f6eb021SLiane Praza assert(0); 62621f6eb021SLiane Praza abort(); 62631f6eb021SLiane Praza } 62641f6eb021SLiane Praza } 62651f6eb021SLiane Praza 62661f6eb021SLiane Praza while ((r = scf_iter_next_property(iter, prop)) == 1) { 62671f6eb021SLiane Praza if (scf_property_get_name(prop, prop_name, nsize) == -1) { 62681f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 62691f6eb021SLiane Praza goto cleanup; 62701f6eb021SLiane Praza } 62711f6eb021SLiane Praza if (scf_tmpl_get_by_prop(t, prop_name, pt, 0) != 0) { 62721f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 62731f6eb021SLiane Praza goto cleanup; 62741f6eb021SLiane Praza } else switch (scf_error()) { 62751f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 62761f6eb021SLiane Praza /* No template. Continue. */ 62771f6eb021SLiane Praza continue; 62781f6eb021SLiane Praza 62791f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 62801f6eb021SLiane Praza default: 62811f6eb021SLiane Praza assert(0); 62821f6eb021SLiane Praza abort(); 62831f6eb021SLiane Praza } 62841f6eb021SLiane Praza } 62851f6eb021SLiane Praza 62861f6eb021SLiane Praza if (_check_property(pt, pg, prop, errs) != 0) 62871f6eb021SLiane Praza goto cleanup; 62881f6eb021SLiane Praza } 62891f6eb021SLiane Praza 62901f6eb021SLiane Praza if (r < 0) { 62911f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 62921f6eb021SLiane Praza goto cleanup; 62931f6eb021SLiane Praza } else { 62941f6eb021SLiane Praza assert(0); 62951f6eb021SLiane Praza abort(); 62961f6eb021SLiane Praza } 62971f6eb021SLiane Praza } 62981f6eb021SLiane Praza 62991f6eb021SLiane Praza scf_tmpl_prop_reset(pt); 63001f6eb021SLiane Praza free(prop_name); 63011f6eb021SLiane Praza prop_name = NULL; 63021f6eb021SLiane Praza /* 63031f6eb021SLiane Praza * Confirm required properties are present. 63041f6eb021SLiane Praza */ 63051f6eb021SLiane Praza while ((r = scf_tmpl_iter_props(t, pt, 63061f6eb021SLiane Praza SCF_PROP_TMPL_FLAG_REQUIRED)) == 0) { 63071f6eb021SLiane Praza scf_type_t prop_type; 63081f6eb021SLiane Praza 63091f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &prop_name) == -1) 63101f6eb021SLiane Praza goto cleanup; 63111f6eb021SLiane Praza 63121f6eb021SLiane Praza /* required properties cannot have type wildcarded */ 63131f6eb021SLiane Praza if (scf_tmpl_prop_type(pt, &prop_type) == -1) { 63141f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 63151f6eb021SLiane Praza (void) scf_set_error( 63161f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 63171f6eb021SLiane Praza goto cleanup; 63181f6eb021SLiane Praza } 63191f6eb021SLiane Praza 63201f6eb021SLiane Praza if (scf_pg_get_property(pg, prop_name, prop) != 0) { 63211f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 63221f6eb021SLiane Praza goto cleanup; 63231f6eb021SLiane Praza } else switch (scf_error()) { 63241f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 63251f6eb021SLiane Praza if (_add_tmpl_missing_prop_error(errs, t, pg, 63261f6eb021SLiane Praza pt) == -1) 63271f6eb021SLiane Praza goto cleanup; 63281f6eb021SLiane Praza break; 63291f6eb021SLiane Praza 63301f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 63311f6eb021SLiane Praza (void) scf_set_error( 63321f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 63331f6eb021SLiane Praza goto cleanup; 63341f6eb021SLiane Praza 63351f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 63361f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 63371f6eb021SLiane Praza default: 63381f6eb021SLiane Praza assert(0); 63391f6eb021SLiane Praza abort(); 63401f6eb021SLiane Praza } 63411f6eb021SLiane Praza } 63421f6eb021SLiane Praza free(prop_name); 63431f6eb021SLiane Praza prop_name = NULL; 63441f6eb021SLiane Praza } 63451f6eb021SLiane Praza if (r < 0) { 63461f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 63471f6eb021SLiane Praza goto cleanup; 63481f6eb021SLiane Praza } else switch (scf_error()) { 63491f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 63501f6eb021SLiane Praza break; 63511f6eb021SLiane Praza 63521f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 63531f6eb021SLiane Praza goto cleanup; 63541f6eb021SLiane Praza 63551f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 63561f6eb021SLiane Praza default: 63571f6eb021SLiane Praza assert(0); 63581f6eb021SLiane Praza abort(); 63591f6eb021SLiane Praza } 63601f6eb021SLiane Praza } 63611f6eb021SLiane Praza 63621f6eb021SLiane Praza ret = 0; 63631f6eb021SLiane Praza cleanup: 63641f6eb021SLiane Praza scf_tmpl_prop_destroy(pt); 63651f6eb021SLiane Praza scf_iter_destroy(iter); 63661f6eb021SLiane Praza scf_property_destroy(prop); 63671f6eb021SLiane Praza free(prop_name); 63681f6eb021SLiane Praza free(pg_type); 63691f6eb021SLiane Praza return (ret); 63701f6eb021SLiane Praza } 63711f6eb021SLiane Praza 63721f6eb021SLiane Praza /* 63731f6eb021SLiane Praza * Checks if instance fmri redefines any pgs defined in restarter or global 63741f6eb021SLiane Praza * Return -1 on failure, sets scf_error() to: 63751f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 63761f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 63771f6eb021SLiane Praza * SCF_ERROR_DELETED 63781f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 63791f6eb021SLiane Praza * SCF_ERROR_INTERNAL 63801f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 63811f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 63821f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 63831f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 63841f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 63851f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 63861f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 63871f6eb021SLiane Praza */ 63881f6eb021SLiane Praza static int 63891f6eb021SLiane Praza _scf_tmpl_check_pg_redef(scf_handle_t *h, const char *fmri, 63901f6eb021SLiane Praza const char *snapname, scf_tmpl_errors_t *errs) 63911f6eb021SLiane Praza { 63921f6eb021SLiane Praza scf_pg_tmpl_t *t = NULL; 63931f6eb021SLiane Praza scf_pg_tmpl_t *r = NULL; 63941f6eb021SLiane Praza char *pg_name = NULL; 63951f6eb021SLiane Praza char *pg_name_r = NULL; 63961f6eb021SLiane Praza char *pg_type = NULL; 63971f6eb021SLiane Praza char *pg_type_r = NULL; 63981f6eb021SLiane Praza char *target = NULL; 63991f6eb021SLiane Praza int ret_val = -1; 64001f6eb021SLiane Praza int ret; 64011f6eb021SLiane Praza 64021f6eb021SLiane Praza t = scf_tmpl_pg_create(h); 64031f6eb021SLiane Praza r = scf_tmpl_pg_create(h); 64041f6eb021SLiane Praza if (t == NULL || r == NULL) 64051f6eb021SLiane Praza goto cleanup; 64061f6eb021SLiane Praza 64071f6eb021SLiane Praza while ((ret = scf_tmpl_iter_pgs(t, fmri, snapname, NULL, 64081f6eb021SLiane Praza SCF_PG_TMPL_FLAG_EXACT)) == 1) { 64091f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &pg_name) == -1) { 64101f6eb021SLiane Praza goto cleanup; 64111f6eb021SLiane Praza } 64121f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &pg_type) == -1) { 64131f6eb021SLiane Praza goto cleanup; 64141f6eb021SLiane Praza } 64151f6eb021SLiane Praza /* look for a redefinition of a global/restarter pg_pattern */ 64161f6eb021SLiane Praza while ((ret = scf_tmpl_iter_pgs(r, fmri, snapname, pg_type, 64171f6eb021SLiane Praza 0)) == 1) { 64181f6eb021SLiane Praza if (scf_tmpl_pg_name(r, &pg_name_r) == -1) { 64191f6eb021SLiane Praza goto cleanup; 64201f6eb021SLiane Praza } else if (strcmp(pg_name_r, SCF_TMPL_WILDCARD) != 0 && 64211f6eb021SLiane Praza strcmp(pg_name, SCF_TMPL_WILDCARD) != 0 && 64221f6eb021SLiane Praza strcmp(pg_name, pg_name_r) != 0) { 64231f6eb021SLiane Praza /* not a match */ 64241f6eb021SLiane Praza free(pg_name_r); 64251f6eb021SLiane Praza pg_name_r = NULL; 64261f6eb021SLiane Praza continue; 64271f6eb021SLiane Praza } 64281f6eb021SLiane Praza if (scf_tmpl_pg_type(r, &pg_type_r) == -1) { 64291f6eb021SLiane Praza goto cleanup; 64301f6eb021SLiane Praza } else if (strcmp(pg_type_r, SCF_TMPL_WILDCARD) != 0 && 64311f6eb021SLiane Praza strcmp(pg_type, SCF_TMPL_WILDCARD) != 0 && 64321f6eb021SLiane Praza strcmp(pg_type, pg_type_r) != 0) { 64331f6eb021SLiane Praza /* not a match */ 64341f6eb021SLiane Praza free(pg_name_r); 64351f6eb021SLiane Praza pg_name_r = NULL; 64361f6eb021SLiane Praza free(pg_type_r); 64371f6eb021SLiane Praza pg_type_r = NULL; 64381f6eb021SLiane Praza continue; 64391f6eb021SLiane Praza } 64401f6eb021SLiane Praza if (scf_tmpl_pg_target(r, &target) == -1) { 64411f6eb021SLiane Praza target = NULL; 64421f6eb021SLiane Praza goto cleanup; 64431f6eb021SLiane Praza } 64441f6eb021SLiane Praza if (strcmp(target, SCF_TM_TARGET_ALL) == 0 || 64451f6eb021SLiane Praza strcmp(target, SCF_TM_TARGET_DELEGATE) == 0) { 64461f6eb021SLiane Praza /* found a pg_pattern redefinition */ 64471f6eb021SLiane Praza if (_add_tmpl_pg_redefine_error(errs, t, 64481f6eb021SLiane Praza r) == -1) 64491f6eb021SLiane Praza goto cleanup; 64501f6eb021SLiane Praza free(pg_name_r); 64511f6eb021SLiane Praza pg_name_r = NULL; 645276fa7285SAntonello Cruz free(pg_type_r); 645376fa7285SAntonello Cruz pg_type_r = NULL; 64541f6eb021SLiane Praza free(target); 64551f6eb021SLiane Praza target = NULL; 64561f6eb021SLiane Praza break; 64571f6eb021SLiane Praza } 64581f6eb021SLiane Praza free(pg_name_r); 64591f6eb021SLiane Praza pg_name_r = NULL; 646076fa7285SAntonello Cruz free(pg_type_r); 646176fa7285SAntonello Cruz pg_type_r = NULL; 64621f6eb021SLiane Praza free(target); 64631f6eb021SLiane Praza target = NULL; 64641f6eb021SLiane Praza } 64651f6eb021SLiane Praza if (ret == -1) 64661f6eb021SLiane Praza goto cleanup; 64671f6eb021SLiane Praza scf_tmpl_pg_reset(r); 64681f6eb021SLiane Praza 64691f6eb021SLiane Praza free(pg_name); 64701f6eb021SLiane Praza free(pg_type); 64711f6eb021SLiane Praza pg_name = NULL; 64721f6eb021SLiane Praza pg_type = NULL; 64731f6eb021SLiane Praza } 64741f6eb021SLiane Praza if (ret == -1) 64751f6eb021SLiane Praza goto cleanup; 64761f6eb021SLiane Praza 64771f6eb021SLiane Praza ret_val = 0; 64781f6eb021SLiane Praza 64791f6eb021SLiane Praza cleanup: 64801f6eb021SLiane Praza scf_tmpl_pg_destroy(t); 64811f6eb021SLiane Praza scf_tmpl_pg_destroy(r); 64821f6eb021SLiane Praza free(pg_name); 64831f6eb021SLiane Praza free(pg_type); 64841f6eb021SLiane Praza free(pg_name_r); 64851f6eb021SLiane Praza free(pg_type_r); 64861f6eb021SLiane Praza free(target); 64871f6eb021SLiane Praza 64881f6eb021SLiane Praza if (ret_val == -1) { 64891f6eb021SLiane Praza if (!ismember(scf_error(), errors_server)) { 64901f6eb021SLiane Praza switch (scf_error()) { 64911f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 64921f6eb021SLiane Praza (void) scf_set_error( 64931f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 64941f6eb021SLiane Praza /*FALLTHROUGH*/ 64951f6eb021SLiane Praza 64961f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 64971f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 64981f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 64991f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 65001f6eb021SLiane Praza break; 65011f6eb021SLiane Praza 65021f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 65031f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 65041f6eb021SLiane Praza default: 65051f6eb021SLiane Praza assert(0); 65061f6eb021SLiane Praza abort(); 65071f6eb021SLiane Praza } 65081f6eb021SLiane Praza } 65091f6eb021SLiane Praza } 65101f6eb021SLiane Praza return (ret_val); 65111f6eb021SLiane Praza } 65121f6eb021SLiane Praza 65131f6eb021SLiane Praza /* 65141f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 65151f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 65161f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 65171f6eb021SLiane Praza * SCF_ERROR_DELETED 65181f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 65191f6eb021SLiane Praza * SCF_ERROR_INTERNAL 65201f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 65211f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 65221f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 65231f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 65241f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 65251f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 65261f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 65271f6eb021SLiane Praza */ 65281f6eb021SLiane Praza int 65291f6eb021SLiane Praza scf_tmpl_validate_fmri(scf_handle_t *h, const char *fmri, const char *snapshot, 65301f6eb021SLiane Praza scf_tmpl_errors_t **errs, int flags) 65311f6eb021SLiane Praza { 65321f6eb021SLiane Praza scf_pg_tmpl_t *t = NULL; 65331f6eb021SLiane Praza scf_iter_t *iter = NULL; 65341f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 65351f6eb021SLiane Praza scf_instance_t *inst = NULL; 65361f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 65371f6eb021SLiane Praza char *type = NULL; 65381f6eb021SLiane Praza char *pg_name = NULL; 65391f6eb021SLiane Praza ssize_t rsize = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1; 65401f6eb021SLiane Praza ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 65411f6eb021SLiane Praza int ret = -1; 65421f6eb021SLiane Praza int r; 65431f6eb021SLiane Praza 65441f6eb021SLiane Praza assert(errs != NULL); 65451f6eb021SLiane Praza 65461f6eb021SLiane Praza if ((*errs = _scf_create_errors(fmri, 1)) == NULL) 65471f6eb021SLiane Praza return (-1); 65481f6eb021SLiane Praza 65491f6eb021SLiane Praza if ((pg = scf_pg_create(h)) == NULL || 65501f6eb021SLiane Praza (iter = scf_iter_create(h)) == NULL || 65511f6eb021SLiane Praza (inst = scf_instance_create(h)) == NULL || 65521f6eb021SLiane Praza (t = scf_tmpl_pg_create(h)) == NULL) { 65531f6eb021SLiane Praza /* 65541f6eb021SLiane Praza * Sets SCF_ERROR_INVALID_ARGUMENT, SCF_ERROR_NO_MEMORY, 65551f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES, SCF_ERROR_INTERNAL or 65561f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED. 65571f6eb021SLiane Praza */ 65581f6eb021SLiane Praza goto cleanup; 65591f6eb021SLiane Praza } 65601f6eb021SLiane Praza 65611f6eb021SLiane Praza if ((type = malloc(rsize)) == NULL || 65621f6eb021SLiane Praza (pg_name = malloc(nsize)) == NULL) { 65631f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 65641f6eb021SLiane Praza goto cleanup; 65651f6eb021SLiane Praza } 65661f6eb021SLiane Praza 65671f6eb021SLiane Praza if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, NULL, 65681f6eb021SLiane Praza SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 65691f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 65701f6eb021SLiane Praza goto cleanup; 65711f6eb021SLiane Praza } else switch (scf_error()) { 65721f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 65731f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 65741f6eb021SLiane Praza /*FALLTHROUGH*/ 65751f6eb021SLiane Praza 65761f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 65771f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 65781f6eb021SLiane Praza goto cleanup; 65791f6eb021SLiane Praza 65801f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 65811f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 65821f6eb021SLiane Praza default: 65831f6eb021SLiane Praza assert(0); 65841f6eb021SLiane Praza abort(); 65851f6eb021SLiane Praza } 65861f6eb021SLiane Praza } 65871f6eb021SLiane Praza 65881f6eb021SLiane Praza if (snapshot == NULL || strcmp(snapshot, "running") == 0 || 65891f6eb021SLiane Praza (flags & SCF_TMPL_VALIDATE_FLAG_CURRENT)) { 65901f6eb021SLiane Praza if (_get_snapshot(inst, NULL, &snap) == -1) 65911f6eb021SLiane Praza goto cleanup; 65921f6eb021SLiane Praza } else { 65931f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 65941f6eb021SLiane Praza if (_get_snapshot(inst, snapshot, &snap) == -1) { 65951f6eb021SLiane Praza goto cleanup; 65961f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 65971f6eb021SLiane Praza goto cleanup; 65981f6eb021SLiane Praza } 65991f6eb021SLiane Praza } 66001f6eb021SLiane Praza if (_scf_tmpl_check_pg_redef(h, fmri, snapshot, *errs) != 0) { 66011f6eb021SLiane Praza goto cleanup; 66021f6eb021SLiane Praza } 66031f6eb021SLiane Praza 66041f6eb021SLiane Praza /* 66051f6eb021SLiane Praza * Check that property groups on this instance conform to the template. 66061f6eb021SLiane Praza */ 66071f6eb021SLiane Praza if (scf_iter_instance_pgs_composed(iter, inst, snap) != 0) { 66081f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 66091f6eb021SLiane Praza goto cleanup; 66101f6eb021SLiane Praza } else { 66111f6eb021SLiane Praza assert(0); 66121f6eb021SLiane Praza abort(); 66131f6eb021SLiane Praza } 66141f6eb021SLiane Praza } 66151f6eb021SLiane Praza 66161f6eb021SLiane Praza while ((r = scf_iter_next_pg(iter, pg)) == 1) { 66171f6eb021SLiane Praza if (scf_pg_get_name(pg, pg_name, nsize) == -1) { 66181f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 66191f6eb021SLiane Praza goto cleanup; 66201f6eb021SLiane Praza } else { 66211f6eb021SLiane Praza assert(0); 66221f6eb021SLiane Praza abort(); 66231f6eb021SLiane Praza } 66241f6eb021SLiane Praza } 66251f6eb021SLiane Praza 66261f6eb021SLiane Praza if (scf_pg_get_type(pg, type, rsize) == -1) { 66271f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 66281f6eb021SLiane Praza goto cleanup; 66291f6eb021SLiane Praza } else { 66301f6eb021SLiane Praza assert(0); 66311f6eb021SLiane Praza abort(); 66321f6eb021SLiane Praza } 66331f6eb021SLiane Praza } 66341f6eb021SLiane Praza 66351f6eb021SLiane Praza if (scf_tmpl_get_by_pg_name(fmri, snapshot, pg_name, type, t, 66361f6eb021SLiane Praza 0) != 0) { 66371f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 66381f6eb021SLiane Praza goto cleanup; 66391f6eb021SLiane Praza } else switch (scf_error()) { 66401f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 66411f6eb021SLiane Praza continue; 66421f6eb021SLiane Praza 66431f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 66441f6eb021SLiane Praza goto cleanup; 66451f6eb021SLiane Praza 66461f6eb021SLiane Praza default: 66471f6eb021SLiane Praza assert(0); 66481f6eb021SLiane Praza abort(); 66491f6eb021SLiane Praza } 66501f6eb021SLiane Praza } 66511f6eb021SLiane Praza 66521f6eb021SLiane Praza if (_check_pg(t, pg, pg_name, type, *errs) != 0) 66531f6eb021SLiane Praza goto cleanup; 66541f6eb021SLiane Praza } 66551f6eb021SLiane Praza if (r < 0) { 66561f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 66571f6eb021SLiane Praza goto cleanup; 66581f6eb021SLiane Praza } else { 66591f6eb021SLiane Praza assert(0); 66601f6eb021SLiane Praza abort(); 66611f6eb021SLiane Praza } 66621f6eb021SLiane Praza } 66631f6eb021SLiane Praza 66641f6eb021SLiane Praza scf_tmpl_pg_reset(t); 66651f6eb021SLiane Praza 66661f6eb021SLiane Praza /* 66671f6eb021SLiane Praza * Confirm required property groups are present. 66681f6eb021SLiane Praza */ 66691f6eb021SLiane Praza while ((r = scf_tmpl_iter_pgs(t, fmri, snapshot, NULL, 66701f6eb021SLiane Praza SCF_PG_TMPL_FLAG_REQUIRED)) == 1) { 66711f6eb021SLiane Praza free(pg_name); 66721f6eb021SLiane Praza free(type); 66731f6eb021SLiane Praza 66741f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &pg_name) == -1) 66751f6eb021SLiane Praza goto cleanup; 66761f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &type) == -1) 66771f6eb021SLiane Praza goto cleanup; 66781f6eb021SLiane Praza /* 66791f6eb021SLiane Praza * required property group templates should not have 66801f6eb021SLiane Praza * wildcarded name or type 66811f6eb021SLiane Praza */ 66821f6eb021SLiane Praza if (strcmp(pg_name, SCF_TMPL_WILDCARD) == 0 || 66831f6eb021SLiane Praza strcmp(type, SCF_TMPL_WILDCARD) == 0) { 66841f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 66851f6eb021SLiane Praza goto cleanup; 66861f6eb021SLiane Praza } 66871f6eb021SLiane Praza 66881f6eb021SLiane Praza if (_get_pg(NULL, inst, snap, pg_name, pg) != 0) { 66891f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 66901f6eb021SLiane Praza goto cleanup; 66911f6eb021SLiane Praza } else switch (scf_error()) { 66921f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 66931f6eb021SLiane Praza if (_add_tmpl_missing_pg_error(*errs, t) == -1) 66941f6eb021SLiane Praza goto cleanup; 66951f6eb021SLiane Praza continue; 66961f6eb021SLiane Praza 66971f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 66981f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 66991f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 67001f6eb021SLiane Praza default: 67011f6eb021SLiane Praza assert(0); 67021f6eb021SLiane Praza abort(); 67031f6eb021SLiane Praza } 67041f6eb021SLiane Praza } 67051f6eb021SLiane Praza } 67061f6eb021SLiane Praza if (r < 0) { 67071f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 67081f6eb021SLiane Praza goto cleanup; 67091f6eb021SLiane Praza } else switch (scf_error()) { 67101f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 67111f6eb021SLiane Praza break; 67121f6eb021SLiane Praza 67131f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 67141f6eb021SLiane Praza goto cleanup; 67151f6eb021SLiane Praza 67161f6eb021SLiane Praza default: 67171f6eb021SLiane Praza assert(0); 67181f6eb021SLiane Praza abort(); 67191f6eb021SLiane Praza } 67201f6eb021SLiane Praza } 67211f6eb021SLiane Praza 67221f6eb021SLiane Praza ret = 0; 67231f6eb021SLiane Praza if ((*errs)->tes_num_errs > 0) 67241f6eb021SLiane Praza ret = 1; 67251f6eb021SLiane Praza cleanup: 67261f6eb021SLiane Praza if (ret != 1) { 67271f6eb021SLiane Praza /* there are no errors to report */ 67281f6eb021SLiane Praza scf_tmpl_errors_destroy(*errs); 67291f6eb021SLiane Praza *errs = NULL; 67301f6eb021SLiane Praza } 67311f6eb021SLiane Praza scf_tmpl_pg_destroy(t); 67321f6eb021SLiane Praza free(type); 67331f6eb021SLiane Praza free(pg_name); 67341f6eb021SLiane Praza 67351f6eb021SLiane Praza scf_iter_destroy(iter); 67361f6eb021SLiane Praza scf_pg_destroy(pg); 67371f6eb021SLiane Praza scf_instance_destroy(inst); 67381f6eb021SLiane Praza scf_snapshot_destroy(snap); 67391f6eb021SLiane Praza 67401f6eb021SLiane Praza return (ret); 67411f6eb021SLiane Praza } 67421f6eb021SLiane Praza 67431f6eb021SLiane Praza void 67441f6eb021SLiane Praza scf_tmpl_errors_destroy(scf_tmpl_errors_t *errs) 67451f6eb021SLiane Praza { 67461f6eb021SLiane Praza int i; 67471f6eb021SLiane Praza scf_tmpl_error_t *e; 67481f6eb021SLiane Praza 67491f6eb021SLiane Praza if (errs == NULL) 67501f6eb021SLiane Praza return; 67511f6eb021SLiane Praza 67521f6eb021SLiane Praza for (i = 0; i < errs->tes_num_errs; ++i) { 67531f6eb021SLiane Praza e = errs->tes_errs[i]; 67541f6eb021SLiane Praza if (errs->tes_flag != 0) { 67551f6eb021SLiane Praza free((char *)e->te_pg_name); 67561f6eb021SLiane Praza free((char *)e->te_prop_name); 67571f6eb021SLiane Praza free((char *)e->te_ev1); 67581f6eb021SLiane Praza free((char *)e->te_ev2); 67591f6eb021SLiane Praza free((char *)e->te_actual); 67601f6eb021SLiane Praza free((char *)e->te_tmpl_fmri); 67611f6eb021SLiane Praza free((char *)e->te_tmpl_pg_name); 67621f6eb021SLiane Praza free((char *)e->te_tmpl_pg_type); 67631f6eb021SLiane Praza free((char *)e->te_tmpl_prop_name); 67641f6eb021SLiane Praza free((char *)e->te_tmpl_prop_type); 67651f6eb021SLiane Praza } 67661f6eb021SLiane Praza free(e); 67671f6eb021SLiane Praza } 67681f6eb021SLiane Praza free((char *)errs->tes_fmri); 67691f6eb021SLiane Praza free((char *)errs->tes_prefix); 67701f6eb021SLiane Praza free(errs->tes_errs); 67711f6eb021SLiane Praza free(errs); 67721f6eb021SLiane Praza } 67731f6eb021SLiane Praza 67741f6eb021SLiane Praza int 67751f6eb021SLiane Praza scf_tmpl_error_source_fmri(const scf_tmpl_error_t *err, char **fmri) 67761f6eb021SLiane Praza { 67771f6eb021SLiane Praza assert(err != NULL); 67781f6eb021SLiane Praza switch (err->te_type) { 67791f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 67801f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 67811f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 67821f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 67831f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 67841f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 67851f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 67861f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 67871f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 67881f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 67891f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 67901f6eb021SLiane Praza *fmri = (char *)err->te_tmpl_fmri; 67911f6eb021SLiane Praza return (0); 67921f6eb021SLiane Praza /*NOTREACHED*/ 67931f6eb021SLiane Praza default: 67941f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 67951f6eb021SLiane Praza } 67961f6eb021SLiane Praza return (-1); 67971f6eb021SLiane Praza } 67981f6eb021SLiane Praza 67991f6eb021SLiane Praza int 68001f6eb021SLiane Praza scf_tmpl_error_type(const scf_tmpl_error_t *err, scf_tmpl_error_type_t *type) 68011f6eb021SLiane Praza { 68021f6eb021SLiane Praza assert(err != NULL); 68031f6eb021SLiane Praza switch (err->te_type) { 68041f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 68051f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 68061f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 68071f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 68081f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 68091f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 68101f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 68111f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 68121f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 68131f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 68141f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 68151f6eb021SLiane Praza *type = err->te_type; 68161f6eb021SLiane Praza return (0); 68171f6eb021SLiane Praza /*NOTREACHED*/ 68181f6eb021SLiane Praza default: 68191f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 68201f6eb021SLiane Praza } 68211f6eb021SLiane Praza return (-1); 68221f6eb021SLiane Praza } 68231f6eb021SLiane Praza 68241f6eb021SLiane Praza int 68251f6eb021SLiane Praza scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t *err, char **name, char **type) 68261f6eb021SLiane Praza { 68271f6eb021SLiane Praza assert(err != NULL); 68281f6eb021SLiane Praza switch (err->te_type) { 68291f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 68301f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 68311f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 68321f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 68331f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 68341f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 68351f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 68361f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 68371f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 68381f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 68391f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 68401f6eb021SLiane Praza if (err->te_tmpl_pg_name != NULL && 68411f6eb021SLiane Praza err->te_tmpl_pg_type != NULL) { 68421f6eb021SLiane Praza if (name != NULL) 68431f6eb021SLiane Praza *name = (char *)err->te_tmpl_pg_name; 68441f6eb021SLiane Praza if (type != NULL) 68451f6eb021SLiane Praza *type = (char *)err->te_tmpl_pg_type; 68461f6eb021SLiane Praza return (0); 68471f6eb021SLiane Praza } 68481f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 68491f6eb021SLiane Praza break; 68501f6eb021SLiane Praza default: 68511f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 68521f6eb021SLiane Praza } 68531f6eb021SLiane Praza return (-1); 68541f6eb021SLiane Praza } 68551f6eb021SLiane Praza 68561f6eb021SLiane Praza int 68571f6eb021SLiane Praza scf_tmpl_error_pg(const scf_tmpl_error_t *err, char **name, char **type) 68581f6eb021SLiane Praza { 68591f6eb021SLiane Praza assert(err != NULL); 68601f6eb021SLiane Praza switch (err->te_type) { 68611f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 68621f6eb021SLiane Praza if (err->te_pg_name != NULL && 68631f6eb021SLiane Praza err->te_actual != NULL) { 68641f6eb021SLiane Praza if (name != NULL) 68651f6eb021SLiane Praza *name = (char *)err->te_pg_name; 68661f6eb021SLiane Praza if (type != NULL) 68671f6eb021SLiane Praza *type = (char *)err->te_actual; 68681f6eb021SLiane Praza return (0); 68691f6eb021SLiane Praza } 68701f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 68711f6eb021SLiane Praza break; 68721f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 68731f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 68741f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 68751f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 68761f6eb021SLiane Praza if (err->te_pg_name != NULL && 68771f6eb021SLiane Praza err->te_tmpl_pg_type != NULL) { 68781f6eb021SLiane Praza if (name != NULL) 68791f6eb021SLiane Praza *name = (char *)err->te_pg_name; 68801f6eb021SLiane Praza if (type != NULL) 68811f6eb021SLiane Praza *type = (char *)err->te_tmpl_pg_type; 68821f6eb021SLiane Praza return (0); 68831f6eb021SLiane Praza } 68841f6eb021SLiane Praza /*FALLTHROUGH*/ 68851f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 68861f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 68871f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 68881f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 68891f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 68901f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 68911f6eb021SLiane Praza break; 68921f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 68931f6eb021SLiane Praza if (err->te_ev1 != NULL && err->te_ev2 != NULL) { 68941f6eb021SLiane Praza if (name != NULL) 68951f6eb021SLiane Praza *name = (char *)err->te_ev1; 68961f6eb021SLiane Praza if (type != NULL) 68971f6eb021SLiane Praza *type = (char *)err->te_ev2; 68981f6eb021SLiane Praza return (0); 68991f6eb021SLiane Praza } 69001f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 69011f6eb021SLiane Praza break; 69021f6eb021SLiane Praza default: 69031f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 69041f6eb021SLiane Praza } 69051f6eb021SLiane Praza return (-1); 69061f6eb021SLiane Praza } 69071f6eb021SLiane Praza 69081f6eb021SLiane Praza int 69091f6eb021SLiane Praza scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t *err, char **name, char **type) 69101f6eb021SLiane Praza { 69111f6eb021SLiane Praza assert(err != NULL); 69121f6eb021SLiane Praza switch (err->te_type) { 69131f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 69141f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 69151f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 69161f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 69171f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 69181f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 69191f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 69201f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 69211f6eb021SLiane Praza if (err->te_tmpl_prop_name != NULL && 69221f6eb021SLiane Praza err->te_tmpl_prop_type != NULL) { 69231f6eb021SLiane Praza if (name != NULL) 69241f6eb021SLiane Praza *name = (char *)err->te_tmpl_prop_name; 69251f6eb021SLiane Praza if (type != NULL) 69261f6eb021SLiane Praza *type = (char *)err->te_tmpl_prop_type; 69271f6eb021SLiane Praza return (0); 69281f6eb021SLiane Praza } 69291f6eb021SLiane Praza /*FALLTHROUGH*/ 69301f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 69311f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 69321f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 69331f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 69341f6eb021SLiane Praza break; 69351f6eb021SLiane Praza default: 69361f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 69371f6eb021SLiane Praza } 69381f6eb021SLiane Praza return (-1); 69391f6eb021SLiane Praza } 69401f6eb021SLiane Praza 69411f6eb021SLiane Praza int 69421f6eb021SLiane Praza scf_tmpl_error_prop(const scf_tmpl_error_t *err, char **name, char **type) 69431f6eb021SLiane Praza { 69441f6eb021SLiane Praza assert(err != NULL); 69451f6eb021SLiane Praza switch (err->te_type) { 69461f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 69471f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 69481f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 69491f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 69501f6eb021SLiane Praza if (err->te_prop_name != NULL && 69511f6eb021SLiane Praza err->te_tmpl_prop_type != NULL) { 69521f6eb021SLiane Praza if (name != NULL) 69531f6eb021SLiane Praza *name = (char *)err->te_prop_name; 69541f6eb021SLiane Praza if (type != NULL) 69551f6eb021SLiane Praza *type = (char *)err->te_tmpl_prop_type; 69561f6eb021SLiane Praza return (0); 69571f6eb021SLiane Praza } 69581f6eb021SLiane Praza /*FALLTHROUGH*/ 69591f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 69601f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 69611f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 69621f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 69631f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 69641f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 69651f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 69661f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 69671f6eb021SLiane Praza break; 69681f6eb021SLiane Praza default: 69691f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 69701f6eb021SLiane Praza } 69711f6eb021SLiane Praza return (-1); 69721f6eb021SLiane Praza } 69731f6eb021SLiane Praza 69741f6eb021SLiane Praza int 69751f6eb021SLiane Praza scf_tmpl_error_value(const scf_tmpl_error_t *err, char **val) 69761f6eb021SLiane Praza { 69771f6eb021SLiane Praza assert(err != NULL); 69781f6eb021SLiane Praza switch (err->te_type) { 69791f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 69801f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 69811f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 69821f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 69831f6eb021SLiane Praza if (err->te_actual != NULL) { 69841f6eb021SLiane Praza if (val != NULL) 69851f6eb021SLiane Praza *val = (char *)err->te_actual; 69861f6eb021SLiane Praza return (0); 69871f6eb021SLiane Praza } 69881f6eb021SLiane Praza /*FALLTHROUGH*/ 69891f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 69901f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 69911f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 69921f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 69931f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 69941f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 69951f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 69961f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 69971f6eb021SLiane Praza break; 69981f6eb021SLiane Praza default: 69991f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 70001f6eb021SLiane Praza } 70011f6eb021SLiane Praza return (-1); 70021f6eb021SLiane Praza } 70031f6eb021SLiane Praza 70041f6eb021SLiane Praza const char * 70051f6eb021SLiane Praza scf_tmpl_visibility_to_string(uint8_t vis) 70061f6eb021SLiane Praza { 70071f6eb021SLiane Praza if (vis == SCF_TMPL_VISIBILITY_READONLY) 70081f6eb021SLiane Praza return (SCF_TM_VISIBILITY_READONLY); 70091f6eb021SLiane Praza else if (vis == SCF_TMPL_VISIBILITY_HIDDEN) 70101f6eb021SLiane Praza return (SCF_TM_VISIBILITY_HIDDEN); 70111f6eb021SLiane Praza else if (vis == SCF_TMPL_VISIBILITY_READWRITE) 70121f6eb021SLiane Praza return (SCF_TM_VISIBILITY_READWRITE); 70131f6eb021SLiane Praza else 70141f6eb021SLiane Praza return ("unknown"); 70151f6eb021SLiane Praza } 7016