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