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