1*1f6eb021SLiane Praza /* 2*1f6eb021SLiane Praza * CDDL HEADER START 3*1f6eb021SLiane Praza * 4*1f6eb021SLiane Praza * The contents of this file are subject to the terms of the 5*1f6eb021SLiane Praza * Common Development and Distribution License (the "License"). 6*1f6eb021SLiane Praza * You may not use this file except in compliance with the License. 7*1f6eb021SLiane Praza * 8*1f6eb021SLiane Praza * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1f6eb021SLiane Praza * or http://www.opensolaris.org/os/licensing. 10*1f6eb021SLiane Praza * See the License for the specific language governing permissions 11*1f6eb021SLiane Praza * and limitations under the License. 12*1f6eb021SLiane Praza * 13*1f6eb021SLiane Praza * When distributing Covered Code, include this CDDL HEADER in each 14*1f6eb021SLiane Praza * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1f6eb021SLiane Praza * If applicable, add the following below this CDDL HEADER, with the 16*1f6eb021SLiane Praza * fields enclosed by brackets "[]" replaced with your own identifying 17*1f6eb021SLiane Praza * information: Portions Copyright [yyyy] [name of copyright owner] 18*1f6eb021SLiane Praza * 19*1f6eb021SLiane Praza * CDDL HEADER END 20*1f6eb021SLiane Praza */ 21*1f6eb021SLiane Praza /* 22*1f6eb021SLiane Praza * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*1f6eb021SLiane Praza * Use is subject to license terms. 24*1f6eb021SLiane Praza */ 25*1f6eb021SLiane Praza 26*1f6eb021SLiane Praza /* 27*1f6eb021SLiane Praza * scf_tmpl.c 28*1f6eb021SLiane Praza * 29*1f6eb021SLiane Praza * This file implements the bulk of the libscf templates interfaces. 30*1f6eb021SLiane Praza * Templates describe metadata about a service or instance in general, 31*1f6eb021SLiane Praza * and individual configuration properties on those services and instances. 32*1f6eb021SLiane Praza * Human-consumable descriptions can be provided, along with definitions 33*1f6eb021SLiane Praza * of valid configuration. See service_bundle.dtd.1 for XML definitions 34*1f6eb021SLiane Praza * of templates, and the svccfg code for information on how those definitions 35*1f6eb021SLiane Praza * are translated into the repository. 36*1f6eb021SLiane Praza * 37*1f6eb021SLiane Praza * The main data structures are scf_pg_tmpl and scf_prop_tmpl. These 38*1f6eb021SLiane Praza * are allocated by the callers through scf_tmpl_[pg|prop]_create(), and 39*1f6eb021SLiane Praza * destroyed with scf_tmpl_[pg|prop]_destroy(). They are populated by 40*1f6eb021SLiane Praza * scf_tmpl_get_by_pg_name(), scf_tmpl_get_by_pg(), and 41*1f6eb021SLiane Praza * scf_tmpl_get_by_prop(). They also store the iterator state for 42*1f6eb021SLiane Praza * scf_tmpl_iter_pgs() and scf_tmpl_iter_props(). 43*1f6eb021SLiane Praza * 44*1f6eb021SLiane Praza * These data structures are then consumed by other functions to 45*1f6eb021SLiane Praza * gather information about the template (e.g. name, description, 46*1f6eb021SLiane Praza * choices, constraints, etc.). 47*1f6eb021SLiane Praza * 48*1f6eb021SLiane Praza * scf_tmpl_validate_fmri() does instance validation against template 49*1f6eb021SLiane Praza * data, and populates a set of template errors which can be explored using 50*1f6eb021SLiane Praza * the scf_tmpl_next_error() and the scf_tmpl_error*() suite of functions. 51*1f6eb021SLiane Praza * 52*1f6eb021SLiane Praza * The main data structures for template errors are scf_tmpl_errors, 53*1f6eb021SLiane Praza * defined in this file, and scf_tmpl_error, defined in libscf_priv.h. 54*1f6eb021SLiane Praza * scf_tmpl_error is shared with svccfg to offer common printing 55*1f6eb021SLiane Praza * of error messages between libscf and svccfg. 56*1f6eb021SLiane Praza * 57*1f6eb021SLiane Praza * General convenience functions are towards the top of this file, 58*1f6eb021SLiane Praza * followed by pg and prop template discovery functions, followed 59*1f6eb021SLiane Praza * by functions which gather information about the discovered 60*1f6eb021SLiane Praza * template. Validation and error functions are at the end of this file. 61*1f6eb021SLiane Praza */ 62*1f6eb021SLiane Praza 63*1f6eb021SLiane Praza #include "lowlevel_impl.h" 64*1f6eb021SLiane Praza #include "libscf_impl.h" 65*1f6eb021SLiane Praza #include <assert.h> 66*1f6eb021SLiane Praza #include <errno.h> 67*1f6eb021SLiane Praza #include <libintl.h> 68*1f6eb021SLiane Praza #include <stdlib.h> 69*1f6eb021SLiane Praza #include <stdio.h> 70*1f6eb021SLiane Praza #include <strings.h> 71*1f6eb021SLiane Praza #include <locale.h> 72*1f6eb021SLiane Praza #include <ctype.h> 73*1f6eb021SLiane Praza #include <inttypes.h> 74*1f6eb021SLiane Praza 75*1f6eb021SLiane Praza #define SCF_TMPL_PG_COMMON_NAME_C "common_name_C" 76*1f6eb021SLiane Praza 77*1f6eb021SLiane Praza #define SCF__TMPL_ITER_NONE 0 78*1f6eb021SLiane Praza #define SCF__TMPL_ITER_INST 1 79*1f6eb021SLiane Praza #define SCF__TMPL_ITER_RESTARTER 2 80*1f6eb021SLiane Praza #define SCF__TMPL_ITER_GLOBAL 3 81*1f6eb021SLiane Praza 82*1f6eb021SLiane Praza #define SCF_TMPL_PG_NT 0 83*1f6eb021SLiane Praza #define SCF_TMPL_PG_N 1 84*1f6eb021SLiane Praza #define SCF_TMPL_PG_T 2 85*1f6eb021SLiane Praza #define SCF_TMPL_PG_WILD 3 86*1f6eb021SLiane Praza 87*1f6eb021SLiane Praza struct scf_pg_tmpl { 88*1f6eb021SLiane Praza int pt_populated; 89*1f6eb021SLiane Praza scf_handle_t *pt_h; 90*1f6eb021SLiane Praza scf_propertygroup_t *pt_pg; 91*1f6eb021SLiane Praza scf_service_t *pt_orig_svc; 92*1f6eb021SLiane Praza scf_service_t *pt_svc; 93*1f6eb021SLiane Praza scf_instance_t *pt_orig_inst; 94*1f6eb021SLiane Praza scf_instance_t *pt_inst; 95*1f6eb021SLiane Praza scf_snapshot_t *pt_snap; 96*1f6eb021SLiane Praza int pt_is_iter; 97*1f6eb021SLiane Praza scf_iter_t *pt_iter; 98*1f6eb021SLiane Praza int pt_iter_last; 99*1f6eb021SLiane Praza }; 100*1f6eb021SLiane Praza 101*1f6eb021SLiane Praza #define SCF_WALK_ERROR -1 102*1f6eb021SLiane Praza #define SCF_WALK_NEXT 0 103*1f6eb021SLiane Praza #define SCF_WALK_DONE 1 104*1f6eb021SLiane Praza 105*1f6eb021SLiane Praza struct pg_tmpl_walk { 106*1f6eb021SLiane Praza const char *pw_snapname; 107*1f6eb021SLiane Praza const char *pw_pgname; 108*1f6eb021SLiane Praza const char *pw_pgtype; 109*1f6eb021SLiane Praza scf_instance_t *pw_inst; 110*1f6eb021SLiane Praza scf_service_t *pw_svc; 111*1f6eb021SLiane Praza scf_snapshot_t *pw_snap; 112*1f6eb021SLiane Praza scf_propertygroup_t *pw_pg; 113*1f6eb021SLiane Praza const char *pw_target; 114*1f6eb021SLiane Praza char *pw_tmpl_pgname; 115*1f6eb021SLiane Praza }; 116*1f6eb021SLiane Praza 117*1f6eb021SLiane Praza typedef struct pg_tmpl_walk pg_tmpl_walk_t; 118*1f6eb021SLiane Praza 119*1f6eb021SLiane Praza typedef int walk_template_inst_func_t(scf_service_t *_svc, 120*1f6eb021SLiane Praza scf_instance_t *_inst, pg_tmpl_walk_t *p); 121*1f6eb021SLiane Praza 122*1f6eb021SLiane Praza struct scf_prop_tmpl { 123*1f6eb021SLiane Praza int prt_populated; 124*1f6eb021SLiane Praza scf_handle_t *prt_h; 125*1f6eb021SLiane Praza scf_pg_tmpl_t *prt_t; 126*1f6eb021SLiane Praza scf_propertygroup_t *prt_pg; 127*1f6eb021SLiane Praza char *prt_pg_name; 128*1f6eb021SLiane Praza scf_iter_t *prt_iter; 129*1f6eb021SLiane Praza }; 130*1f6eb021SLiane Praza 131*1f6eb021SLiane Praza /* 132*1f6eb021SLiane Praza * Common server errors are usually passed back to the caller. This 133*1f6eb021SLiane Praza * array defines them centrally so that they don't need to be enumerated 134*1f6eb021SLiane Praza * in every libscf call. 135*1f6eb021SLiane Praza */ 136*1f6eb021SLiane Praza static const scf_error_t errors_server[] = { 137*1f6eb021SLiane Praza SCF_ERROR_BACKEND_ACCESS, 138*1f6eb021SLiane Praza SCF_ERROR_CONNECTION_BROKEN, 139*1f6eb021SLiane Praza SCF_ERROR_DELETED, 140*1f6eb021SLiane Praza SCF_ERROR_HANDLE_DESTROYED, 141*1f6eb021SLiane Praza SCF_ERROR_INTERNAL, 142*1f6eb021SLiane Praza SCF_ERROR_NO_MEMORY, 143*1f6eb021SLiane Praza SCF_ERROR_NO_RESOURCES, 144*1f6eb021SLiane Praza SCF_ERROR_NOT_BOUND, 145*1f6eb021SLiane Praza SCF_ERROR_PERMISSION_DENIED, 146*1f6eb021SLiane Praza 0 147*1f6eb021SLiane Praza }; 148*1f6eb021SLiane Praza 149*1f6eb021SLiane Praza /* 150*1f6eb021SLiane Praza * int ismember() 151*1f6eb021SLiane Praza * 152*1f6eb021SLiane Praza * Returns 1 if the supplied error is a member of the error array, 0 153*1f6eb021SLiane Praza * if it is not. 154*1f6eb021SLiane Praza */ 155*1f6eb021SLiane Praza static scf_error_t 156*1f6eb021SLiane Praza ismember(const int error, const scf_error_t error_array[]) 157*1f6eb021SLiane Praza { 158*1f6eb021SLiane Praza int i; 159*1f6eb021SLiane Praza 160*1f6eb021SLiane Praza for (i = 0; error_array[i] != 0; ++i) { 161*1f6eb021SLiane Praza if (error == error_array[i]) 162*1f6eb021SLiane Praza return (1); 163*1f6eb021SLiane Praza } 164*1f6eb021SLiane Praza 165*1f6eb021SLiane Praza return (0); 166*1f6eb021SLiane Praza } 167*1f6eb021SLiane Praza 168*1f6eb021SLiane Praza /* 169*1f6eb021SLiane Praza * char *_scf_tmpl_get_fmri() 170*1f6eb021SLiane Praza * 171*1f6eb021SLiane Praza * Given a pg_tmpl, returns the FMRI of the service or instance that 172*1f6eb021SLiane Praza * template describes. The allocated string must be freed with free(). 173*1f6eb021SLiane Praza * 174*1f6eb021SLiane Praza * On failure, returns NULL and sets scf_error() to _CONNECTION_BROKEN, 175*1f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 176*1f6eb021SLiane Praza */ 177*1f6eb021SLiane Praza static char * 178*1f6eb021SLiane Praza _scf_tmpl_get_fmri(const scf_pg_tmpl_t *t) 179*1f6eb021SLiane Praza { 180*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1; 181*1f6eb021SLiane Praza int r; 182*1f6eb021SLiane Praza char *buf = malloc(sz); 183*1f6eb021SLiane Praza 184*1f6eb021SLiane Praza assert(t->pt_svc != NULL || t->pt_inst != NULL); 185*1f6eb021SLiane Praza assert(t->pt_svc == NULL || t->pt_inst == NULL); 186*1f6eb021SLiane Praza 187*1f6eb021SLiane Praza if (buf == NULL) { 188*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 189*1f6eb021SLiane Praza return (buf); 190*1f6eb021SLiane Praza } 191*1f6eb021SLiane Praza 192*1f6eb021SLiane Praza if (t->pt_inst != NULL) 193*1f6eb021SLiane Praza r = scf_instance_to_fmri(t->pt_inst, buf, sz); 194*1f6eb021SLiane Praza else 195*1f6eb021SLiane Praza r = scf_service_to_fmri(t->pt_svc, buf, sz); 196*1f6eb021SLiane Praza 197*1f6eb021SLiane Praza if (r == -1) { 198*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 199*1f6eb021SLiane Praza free(buf); 200*1f6eb021SLiane Praza buf = NULL; 201*1f6eb021SLiane Praza } else { 202*1f6eb021SLiane Praza assert(0); 203*1f6eb021SLiane Praza abort(); 204*1f6eb021SLiane Praza } 205*1f6eb021SLiane Praza } 206*1f6eb021SLiane Praza 207*1f6eb021SLiane Praza return (buf); 208*1f6eb021SLiane Praza } 209*1f6eb021SLiane Praza 210*1f6eb021SLiane Praza /* 211*1f6eb021SLiane Praza * char *_scf_get_pg_type() 212*1f6eb021SLiane Praza * 213*1f6eb021SLiane Praza * Given a propertygroup, returns an allocated string containing the 214*1f6eb021SLiane Praza * type. The string must be freed with free(). 215*1f6eb021SLiane Praza * 216*1f6eb021SLiane Praza * On failure, returns NULL and sets scf_error() to: _CONNECTION_BROKEN, 217*1f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 218*1f6eb021SLiane Praza */ 219*1f6eb021SLiane Praza static char * 220*1f6eb021SLiane Praza _scf_get_pg_type(scf_propertygroup_t *pg) 221*1f6eb021SLiane Praza { 222*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1; 223*1f6eb021SLiane Praza char *buf = malloc(sz); 224*1f6eb021SLiane Praza 225*1f6eb021SLiane Praza if (buf == NULL) { 226*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 227*1f6eb021SLiane Praza } else if (scf_pg_get_type(pg, buf, sz) == -1) { 228*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 229*1f6eb021SLiane Praza free(buf); 230*1f6eb021SLiane Praza buf = NULL; 231*1f6eb021SLiane Praza } else { 232*1f6eb021SLiane Praza assert(0); 233*1f6eb021SLiane Praza abort(); 234*1f6eb021SLiane Praza } 235*1f6eb021SLiane Praza } 236*1f6eb021SLiane Praza 237*1f6eb021SLiane Praza return (buf); 238*1f6eb021SLiane Praza } 239*1f6eb021SLiane Praza 240*1f6eb021SLiane Praza /* 241*1f6eb021SLiane Praza * char *_scf_get_prop_name() 242*1f6eb021SLiane Praza * 243*1f6eb021SLiane Praza * Given a property, returns the name in an allocated string. The string must 244*1f6eb021SLiane Praza * be freed with free(). 245*1f6eb021SLiane Praza * 246*1f6eb021SLiane Praza * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN, 247*1f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 248*1f6eb021SLiane Praza */ 249*1f6eb021SLiane Praza static char * 250*1f6eb021SLiane Praza _scf_get_prop_name(scf_property_t *prop) 251*1f6eb021SLiane Praza { 252*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 253*1f6eb021SLiane Praza char *buf = malloc(sz); 254*1f6eb021SLiane Praza 255*1f6eb021SLiane Praza if (buf == NULL) { 256*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 257*1f6eb021SLiane Praza } else if (scf_property_get_name(prop, buf, sz) == -1) { 258*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 259*1f6eb021SLiane Praza free(buf); 260*1f6eb021SLiane Praza buf = NULL; 261*1f6eb021SLiane Praza } else { 262*1f6eb021SLiane Praza assert(0); 263*1f6eb021SLiane Praza abort(); 264*1f6eb021SLiane Praza } 265*1f6eb021SLiane Praza } 266*1f6eb021SLiane Praza 267*1f6eb021SLiane Praza return (buf); 268*1f6eb021SLiane Praza } 269*1f6eb021SLiane Praza 270*1f6eb021SLiane Praza /* 271*1f6eb021SLiane Praza * char *_scf_get_prop_type() 272*1f6eb021SLiane Praza * 273*1f6eb021SLiane Praza * Given a property, returns the type in an allocated string. The string must 274*1f6eb021SLiane Praza * be freed with free(). 275*1f6eb021SLiane Praza * 276*1f6eb021SLiane Praza * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN, 277*1f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 278*1f6eb021SLiane Praza */ 279*1f6eb021SLiane Praza static char * 280*1f6eb021SLiane Praza _scf_get_prop_type(scf_property_t *prop) 281*1f6eb021SLiane Praza { 282*1f6eb021SLiane Praza scf_type_t type; 283*1f6eb021SLiane Praza char *ret; 284*1f6eb021SLiane Praza 285*1f6eb021SLiane Praza if (scf_property_type(prop, &type) == -1) { 286*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 287*1f6eb021SLiane Praza return (NULL); 288*1f6eb021SLiane Praza } else { 289*1f6eb021SLiane Praza assert(0); 290*1f6eb021SLiane Praza abort(); 291*1f6eb021SLiane Praza } 292*1f6eb021SLiane Praza } 293*1f6eb021SLiane Praza 294*1f6eb021SLiane Praza ret = strdup(scf_type_to_string(type)); 295*1f6eb021SLiane Praza if (ret == NULL) 296*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 297*1f6eb021SLiane Praza 298*1f6eb021SLiane Praza return (ret); 299*1f6eb021SLiane Praza } 300*1f6eb021SLiane Praza 301*1f6eb021SLiane Praza /* 302*1f6eb021SLiane Praza * int _read_single_value_from_pg() 303*1f6eb021SLiane Praza * 304*1f6eb021SLiane Praza * Reads a single value from the pg and property name specified. On success, 305*1f6eb021SLiane Praza * returns an allocated value that must be freed. 306*1f6eb021SLiane Praza * 307*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 308*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 309*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 310*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 311*1f6eb021SLiane Praza * Property has more than one value associated with it. 312*1f6eb021SLiane Praza * SCF_ERROR_DELETED 313*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 314*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 315*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 316*1f6eb021SLiane Praza * prop_name not a valid property name. 317*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 318*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 319*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 320*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 321*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 322*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 323*1f6eb021SLiane Praza * Property group specified by pg is not set. 324*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 325*1f6eb021SLiane Praza */ 326*1f6eb021SLiane Praza static int 327*1f6eb021SLiane Praza _read_single_value_from_pg(scf_propertygroup_t *pg, const char *prop_name, 328*1f6eb021SLiane Praza scf_value_t **val) 329*1f6eb021SLiane Praza { 330*1f6eb021SLiane Praza scf_handle_t *h; 331*1f6eb021SLiane Praza scf_property_t *prop; 332*1f6eb021SLiane Praza int ret = 0; 333*1f6eb021SLiane Praza 334*1f6eb021SLiane Praza assert(val != NULL); 335*1f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) { 336*1f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 337*1f6eb021SLiane Praza return (-1); 338*1f6eb021SLiane Praza } 339*1f6eb021SLiane Praza 340*1f6eb021SLiane Praza prop = scf_property_create(h); 341*1f6eb021SLiane Praza *val = scf_value_create(h); 342*1f6eb021SLiane Praza 343*1f6eb021SLiane Praza if (prop == NULL || *val == NULL) { 344*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 345*1f6eb021SLiane Praza goto read_single_value_from_pg_fail; 346*1f6eb021SLiane Praza } 347*1f6eb021SLiane Praza 348*1f6eb021SLiane Praza if (scf_pg_get_property(pg, prop_name, prop) != 0) { 349*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 350*1f6eb021SLiane Praza goto read_single_value_from_pg_fail; 351*1f6eb021SLiane Praza } 352*1f6eb021SLiane Praza 353*1f6eb021SLiane Praza if (scf_property_get_value(prop, *val) == -1) { 354*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 355*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 356*1f6eb021SLiane Praza goto read_single_value_from_pg_fail; 357*1f6eb021SLiane Praza } 358*1f6eb021SLiane Praza 359*1f6eb021SLiane Praza goto read_single_value_from_pg_done; 360*1f6eb021SLiane Praza 361*1f6eb021SLiane Praza read_single_value_from_pg_fail: 362*1f6eb021SLiane Praza scf_value_destroy(*val); 363*1f6eb021SLiane Praza *val = NULL; 364*1f6eb021SLiane Praza ret = -1; 365*1f6eb021SLiane Praza 366*1f6eb021SLiane Praza read_single_value_from_pg_done: 367*1f6eb021SLiane Praza scf_property_destroy(prop); 368*1f6eb021SLiane Praza return (ret); 369*1f6eb021SLiane Praza } 370*1f6eb021SLiane Praza 371*1f6eb021SLiane Praza /* 372*1f6eb021SLiane Praza * char *_scf_read_single_astring_from_pg() 373*1f6eb021SLiane Praza * 374*1f6eb021SLiane Praza * Reads an astring from the pg and property name specified. On success, 375*1f6eb021SLiane Praza * returns an allocated string. The string must be freed with free(). 376*1f6eb021SLiane Praza * 377*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 378*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 379*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 380*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 381*1f6eb021SLiane Praza * Property has more than one value associated with it. 382*1f6eb021SLiane Praza * SCF_ERROR_DELETED 383*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 384*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 385*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 386*1f6eb021SLiane Praza * prop_name not a valid property name. 387*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 388*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 389*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 390*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 391*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 392*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 393*1f6eb021SLiane Praza * The property group specified by pg is not set. 394*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 395*1f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 396*1f6eb021SLiane Praza */ 397*1f6eb021SLiane Praza char * 398*1f6eb021SLiane Praza _scf_read_single_astring_from_pg(scf_propertygroup_t *pg, const char *prop_name) 399*1f6eb021SLiane Praza { 400*1f6eb021SLiane Praza scf_value_t *val; 401*1f6eb021SLiane Praza char *ret = NULL; 402*1f6eb021SLiane Praza ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 403*1f6eb021SLiane Praza 404*1f6eb021SLiane Praza assert(rsize != 0); 405*1f6eb021SLiane Praza if (_read_single_value_from_pg(pg, prop_name, &val) == -1) 406*1f6eb021SLiane Praza return (NULL); 407*1f6eb021SLiane Praza 408*1f6eb021SLiane Praza ret = malloc(rsize); 409*1f6eb021SLiane Praza if (ret == NULL) { 410*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 411*1f6eb021SLiane Praza goto cleanup; 412*1f6eb021SLiane Praza } 413*1f6eb021SLiane Praza 414*1f6eb021SLiane Praza if (scf_value_get_astring(val, ret, rsize) < 0) { 415*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 416*1f6eb021SLiane Praza free(ret); 417*1f6eb021SLiane Praza ret = NULL; 418*1f6eb021SLiane Praza } 419*1f6eb021SLiane Praza 420*1f6eb021SLiane Praza cleanup: 421*1f6eb021SLiane Praza scf_value_destroy(val); 422*1f6eb021SLiane Praza return (ret); 423*1f6eb021SLiane Praza } 424*1f6eb021SLiane Praza 425*1f6eb021SLiane Praza /* 426*1f6eb021SLiane Praza * char *_scf_read_tmpl_prop_type_as_string() 427*1f6eb021SLiane Praza * 428*1f6eb021SLiane Praza * Reads the property type and returns it as an allocated string. The string 429*1f6eb021SLiane Praza * must be freed with free(). 430*1f6eb021SLiane Praza * 431*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _BACKEND_ACCESS, 432*1f6eb021SLiane Praza * _CONNECTION_BROKEN, _DELETED, _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, 433*1f6eb021SLiane Praza * _NO_RESOURCES, _NOT_BOUND, _PERMISSION_DENIED, or _TEMPLATE_INVALID. 434*1f6eb021SLiane Praza */ 435*1f6eb021SLiane Praza char * 436*1f6eb021SLiane Praza _scf_read_tmpl_prop_type_as_string(const scf_prop_tmpl_t *pt) 437*1f6eb021SLiane Praza { 438*1f6eb021SLiane Praza char *type; 439*1f6eb021SLiane Praza 440*1f6eb021SLiane Praza type = _scf_read_single_astring_from_pg(pt->prt_pg, 441*1f6eb021SLiane Praza SCF_PROPERTY_TM_TYPE); 442*1f6eb021SLiane Praza if (type == NULL) { 443*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 444*1f6eb021SLiane Praza return (NULL); 445*1f6eb021SLiane Praza } else switch (scf_error()) { 446*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 447*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 448*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 449*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 450*1f6eb021SLiane Praza return (NULL); 451*1f6eb021SLiane Praza 452*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 453*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 454*1f6eb021SLiane Praza default: 455*1f6eb021SLiane Praza assert(0); 456*1f6eb021SLiane Praza abort(); 457*1f6eb021SLiane Praza } 458*1f6eb021SLiane Praza } 459*1f6eb021SLiane Praza 460*1f6eb021SLiane Praza return (type); 461*1f6eb021SLiane Praza } 462*1f6eb021SLiane Praza 463*1f6eb021SLiane Praza /* 464*1f6eb021SLiane Praza * int _read_single_boolean_from_pg() 465*1f6eb021SLiane Praza * 466*1f6eb021SLiane Praza * Reads a boolean from the pg and property name specified. 467*1f6eb021SLiane Praza * 468*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 469*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 470*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 471*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 472*1f6eb021SLiane Praza * Property has more than one value associated with it. 473*1f6eb021SLiane Praza * SCF_ERROR_DELETED 474*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 475*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 476*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 477*1f6eb021SLiane Praza * prop_name is not a valid property name. 478*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 479*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 480*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 481*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 482*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 483*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 484*1f6eb021SLiane Praza * The property group specified by pg is not set. 485*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 486*1f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 487*1f6eb021SLiane Praza */ 488*1f6eb021SLiane Praza static int 489*1f6eb021SLiane Praza _read_single_boolean_from_pg(scf_propertygroup_t *pg, const char *prop_name, 490*1f6eb021SLiane Praza uint8_t *bool) 491*1f6eb021SLiane Praza { 492*1f6eb021SLiane Praza scf_value_t *val; 493*1f6eb021SLiane Praza int ret = 0; 494*1f6eb021SLiane Praza 495*1f6eb021SLiane Praza if (_read_single_value_from_pg(pg, prop_name, &val) == -1) 496*1f6eb021SLiane Praza return (-1); 497*1f6eb021SLiane Praza 498*1f6eb021SLiane Praza if (scf_value_get_boolean(val, bool) < 0) { 499*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 500*1f6eb021SLiane Praza ret = -1; 501*1f6eb021SLiane Praza } 502*1f6eb021SLiane Praza 503*1f6eb021SLiane Praza scf_value_destroy(val); 504*1f6eb021SLiane Praza return (ret); 505*1f6eb021SLiane Praza } 506*1f6eb021SLiane Praza 507*1f6eb021SLiane Praza /* 508*1f6eb021SLiane Praza * char **_append_astrings_values() 509*1f6eb021SLiane Praza * 510*1f6eb021SLiane Praza * This function reads the values from the property prop_name in pg and 511*1f6eb021SLiane Praza * appends to an existing scf_values_t *vals. vals may be empty, but 512*1f6eb021SLiane Praza * must exist. The function skips over zero-length and duplicate values. 513*1f6eb021SLiane Praza * 514*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 515*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 516*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 517*1f6eb021SLiane Praza * SCF_ERROR_DELETED 518*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 519*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 520*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 521*1f6eb021SLiane Praza * prop_name is not a valid property name. 522*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 523*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 524*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 525*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 526*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 527*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 528*1f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 529*1f6eb021SLiane Praza */ 530*1f6eb021SLiane Praza static char ** 531*1f6eb021SLiane Praza _append_astrings_values(scf_propertygroup_t *pg, const char *prop_name, 532*1f6eb021SLiane Praza scf_values_t *vals) 533*1f6eb021SLiane Praza { 534*1f6eb021SLiane Praza scf_handle_t *h; 535*1f6eb021SLiane Praza scf_property_t *prop; 536*1f6eb021SLiane Praza scf_value_t *val; 537*1f6eb021SLiane Praza scf_iter_t *iter; 538*1f6eb021SLiane Praza ssize_t rsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 539*1f6eb021SLiane Praza int err, count, cursz, i; 540*1f6eb021SLiane Praza 541*1f6eb021SLiane Praza assert(vals != NULL); 542*1f6eb021SLiane Praza assert(vals->value_type == SCF_TYPE_ASTRING); 543*1f6eb021SLiane Praza assert(vals->reserved == NULL); 544*1f6eb021SLiane Praza count = vals->value_count; 545*1f6eb021SLiane Praza if (count == 0) { 546*1f6eb021SLiane Praza cursz = 8; 547*1f6eb021SLiane Praza vals->values.v_astring = calloc(cursz, sizeof (char *)); 548*1f6eb021SLiane Praza if (vals->values.v_astring == NULL) { 549*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 550*1f6eb021SLiane Praza return (NULL); 551*1f6eb021SLiane Praza } 552*1f6eb021SLiane Praza } else { 553*1f6eb021SLiane Praza /* 554*1f6eb021SLiane Praza * The array may be bigger, but it is irrelevant since 555*1f6eb021SLiane Praza * we will always re-allocate a new one. 556*1f6eb021SLiane Praza */ 557*1f6eb021SLiane Praza cursz = count; 558*1f6eb021SLiane Praza } 559*1f6eb021SLiane Praza 560*1f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) { 561*1f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 562*1f6eb021SLiane Praza return (NULL); 563*1f6eb021SLiane Praza } 564*1f6eb021SLiane Praza 565*1f6eb021SLiane Praza prop = scf_property_create(h); 566*1f6eb021SLiane Praza val = scf_value_create(h); 567*1f6eb021SLiane Praza iter = scf_iter_create(h); 568*1f6eb021SLiane Praza 569*1f6eb021SLiane Praza if (prop == NULL || val == NULL || iter == NULL) { 570*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 571*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 572*1f6eb021SLiane Praza } 573*1f6eb021SLiane Praza 574*1f6eb021SLiane Praza if (scf_pg_get_property(pg, prop_name, prop) != 0) { 575*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 576*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 577*1f6eb021SLiane Praza } 578*1f6eb021SLiane Praza 579*1f6eb021SLiane Praza if (scf_iter_property_values(iter, prop) != 0) { 580*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 581*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 582*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 583*1f6eb021SLiane Praza } 584*1f6eb021SLiane Praza 585*1f6eb021SLiane Praza while ((err = scf_iter_next_value(iter, val)) == 1) { 586*1f6eb021SLiane Praza int flag; 587*1f6eb021SLiane Praza int r; 588*1f6eb021SLiane Praza 589*1f6eb021SLiane Praza if (count + 1 >= cursz) { 590*1f6eb021SLiane Praza void *aux; 591*1f6eb021SLiane Praza 592*1f6eb021SLiane Praza cursz *= 2; 593*1f6eb021SLiane Praza if ((aux = calloc(cursz, sizeof (char *))) == NULL) { 594*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 595*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 596*1f6eb021SLiane Praza } 597*1f6eb021SLiane Praza (void) memcpy(aux, vals->values.v_astring, 598*1f6eb021SLiane Praza count * sizeof (char *)); 599*1f6eb021SLiane Praza free(vals->values.v_astring); 600*1f6eb021SLiane Praza vals->values.v_astring = aux; 601*1f6eb021SLiane Praza } 602*1f6eb021SLiane Praza 603*1f6eb021SLiane Praza vals->values.v_astring[count] = malloc(rsize); 604*1f6eb021SLiane Praza if (vals->values.v_astring[count] == NULL) { 605*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 606*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 607*1f6eb021SLiane Praza } 608*1f6eb021SLiane Praza 609*1f6eb021SLiane Praza if ((r = scf_value_get_astring(val, 610*1f6eb021SLiane Praza vals->values.v_astring[count], rsize)) <= 0) { 611*1f6eb021SLiane Praza /* discard zero length strings */ 612*1f6eb021SLiane Praza if (r == 0) { 613*1f6eb021SLiane Praza free(vals->values.v_astring[count]); 614*1f6eb021SLiane Praza continue; 615*1f6eb021SLiane Praza } 616*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 617*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 618*1f6eb021SLiane Praza } 619*1f6eb021SLiane Praza for (i = 0, flag = 0; i < count; ++i) { 620*1f6eb021SLiane Praza /* find and discard duplicates */ 621*1f6eb021SLiane Praza if (strncmp(vals->values.v_astring[i], 622*1f6eb021SLiane Praza vals->values.v_astring[count], rsize) == 0) { 623*1f6eb021SLiane Praza free(vals->values.v_astring[count]); 624*1f6eb021SLiane Praza flag = 1; 625*1f6eb021SLiane Praza break; 626*1f6eb021SLiane Praza } 627*1f6eb021SLiane Praza } 628*1f6eb021SLiane Praza if (flag == 1) 629*1f6eb021SLiane Praza continue; 630*1f6eb021SLiane Praza 631*1f6eb021SLiane Praza count++; 632*1f6eb021SLiane Praza } 633*1f6eb021SLiane Praza 634*1f6eb021SLiane Praza vals->value_count = count; 635*1f6eb021SLiane Praza 636*1f6eb021SLiane Praza if (err != 0) { 637*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 638*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 639*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 640*1f6eb021SLiane Praza goto append_single_astring_from_pg_fail; 641*1f6eb021SLiane Praza } else { 642*1f6eb021SLiane Praza vals->values_as_strings = vals->values.v_astring; 643*1f6eb021SLiane Praza } 644*1f6eb021SLiane Praza 645*1f6eb021SLiane Praza goto append_single_astring_from_pg_done; 646*1f6eb021SLiane Praza 647*1f6eb021SLiane Praza append_single_astring_from_pg_fail: 648*1f6eb021SLiane Praza for (i = 0; i <= count; ++i) { 649*1f6eb021SLiane Praza if (vals->values.v_astring[i] != NULL) 650*1f6eb021SLiane Praza free(vals->values.v_astring[i]); 651*1f6eb021SLiane Praza vals->values.v_astring[i] = NULL; 652*1f6eb021SLiane Praza } 653*1f6eb021SLiane Praza free(vals->values.v_astring); 654*1f6eb021SLiane Praza vals->values.v_astring = NULL; 655*1f6eb021SLiane Praza vals->value_count = 0; 656*1f6eb021SLiane Praza 657*1f6eb021SLiane Praza append_single_astring_from_pg_done: 658*1f6eb021SLiane Praza scf_iter_destroy(iter); 659*1f6eb021SLiane Praza scf_property_destroy(prop); 660*1f6eb021SLiane Praza scf_value_destroy(val); 661*1f6eb021SLiane Praza return (vals->values.v_astring); 662*1f6eb021SLiane Praza } 663*1f6eb021SLiane Praza 664*1f6eb021SLiane Praza /* 665*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 666*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 667*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 668*1f6eb021SLiane Praza * SCF_ERROR_DELETED 669*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 670*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 671*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 672*1f6eb021SLiane Praza * prop_name is not a valid property name. 673*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 674*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 675*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 676*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 677*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 678*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 679*1f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 680*1f6eb021SLiane Praza */ 681*1f6eb021SLiane Praza static char ** 682*1f6eb021SLiane Praza _read_astrings_values(scf_propertygroup_t *pg, const char *prop_name, 683*1f6eb021SLiane Praza scf_values_t *vals) 684*1f6eb021SLiane Praza { 685*1f6eb021SLiane Praza assert(vals != NULL); 686*1f6eb021SLiane Praza vals->value_count = 0; 687*1f6eb021SLiane Praza vals->value_type = SCF_TYPE_ASTRING; 688*1f6eb021SLiane Praza vals->reserved = NULL; 689*1f6eb021SLiane Praza return (_append_astrings_values(pg, prop_name, vals)); 690*1f6eb021SLiane Praza } 691*1f6eb021SLiane Praza 692*1f6eb021SLiane Praza void 693*1f6eb021SLiane Praza _scf_sanitize_locale(char *locale) 694*1f6eb021SLiane Praza { 695*1f6eb021SLiane Praza for (; *locale != '\0'; locale++) 696*1f6eb021SLiane Praza if (!isalnum(*locale) && *locale != '_') 697*1f6eb021SLiane Praza *locale = '_'; 698*1f6eb021SLiane Praza } 699*1f6eb021SLiane Praza 700*1f6eb021SLiane Praza /* 701*1f6eb021SLiane Praza * The returned string needs to be freed by the caller 702*1f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error() to: 703*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 704*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 705*1f6eb021SLiane Praza * Name isn't short enough to add the locale to. 706*1f6eb021SLiane Praza */ 707*1f6eb021SLiane Praza static char * 708*1f6eb021SLiane Praza _add_locale_to_name(const char *name, const char *locale) 709*1f6eb021SLiane Praza { 710*1f6eb021SLiane Praza char *lname = NULL; 711*1f6eb021SLiane Praza ssize_t lsz; 712*1f6eb021SLiane Praza char *loc; 713*1f6eb021SLiane Praza 714*1f6eb021SLiane Praza if (locale == NULL) 715*1f6eb021SLiane Praza locale = setlocale(LC_MESSAGES, NULL); 716*1f6eb021SLiane Praza loc = strdup(locale); 717*1f6eb021SLiane Praza if (loc == NULL) { 718*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 719*1f6eb021SLiane Praza return (NULL); 720*1f6eb021SLiane Praza } else { 721*1f6eb021SLiane Praza _scf_sanitize_locale(loc); 722*1f6eb021SLiane Praza } 723*1f6eb021SLiane Praza 724*1f6eb021SLiane Praza lsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 725*1f6eb021SLiane Praza lname = malloc(lsz); 726*1f6eb021SLiane Praza if (lname == NULL) { 727*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 728*1f6eb021SLiane Praza goto cleanup; 729*1f6eb021SLiane Praza } 730*1f6eb021SLiane Praza 731*1f6eb021SLiane Praza (void) strlcpy(lname, name, lsz); 732*1f6eb021SLiane Praza if (strlcat(lname, loc, lsz) >= lsz) { 733*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 734*1f6eb021SLiane Praza free(lname); 735*1f6eb021SLiane Praza lname = NULL; 736*1f6eb021SLiane Praza } 737*1f6eb021SLiane Praza cleanup: 738*1f6eb021SLiane Praza free(loc); 739*1f6eb021SLiane Praza 740*1f6eb021SLiane Praza return (lname); 741*1f6eb021SLiane Praza } 742*1f6eb021SLiane Praza 743*1f6eb021SLiane Praza /* 744*1f6eb021SLiane Praza * char *_tmpl_pg_name(pg, type, use_type) 745*1f6eb021SLiane Praza * 746*1f6eb021SLiane Praza * pg and type can both be NULL. Returns the name of the most specific 747*1f6eb021SLiane Praza * template property group name based on the inputs. 748*1f6eb021SLiane Praza * If use_type is set and pg is not NULL, a property group name for a 749*1f6eb021SLiane Praza * property group template that has type defined is returned, even if no 750*1f6eb021SLiane Praza * type is provided. 751*1f6eb021SLiane Praza * 752*1f6eb021SLiane Praza * Returns NULL on failure and sets scf_error() to: 753*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 754*1f6eb021SLiane Praza * can't combine the arguments and get a reasonable length name 755*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 756*1f6eb021SLiane Praza * 757*1f6eb021SLiane Praza */ 758*1f6eb021SLiane Praza static char * 759*1f6eb021SLiane Praza _tmpl_pg_name(const char *pg, const char *type, int use_type) 760*1f6eb021SLiane Praza { 761*1f6eb021SLiane Praza char *name; 762*1f6eb021SLiane Praza ssize_t limit, size = 0; 763*1f6eb021SLiane Praza 764*1f6eb021SLiane Praza limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 765*1f6eb021SLiane Praza name = malloc(limit); 766*1f6eb021SLiane Praza if (name == NULL) { 767*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 768*1f6eb021SLiane Praza return (NULL); 769*1f6eb021SLiane Praza } 770*1f6eb021SLiane Praza 771*1f6eb021SLiane Praza if (pg == NULL && type == NULL) { 772*1f6eb021SLiane Praza if (strlcpy(name, SCF_PG_TM_PG_PATTERN_PREFIX, limit) >= 773*1f6eb021SLiane Praza limit) { 774*1f6eb021SLiane Praza assert(0); 775*1f6eb021SLiane Praza abort(); 776*1f6eb021SLiane Praza } 777*1f6eb021SLiane Praza return (name); 778*1f6eb021SLiane Praza } else if (pg != NULL && type != NULL) { 779*1f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 780*1f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg); 781*1f6eb021SLiane Praza } else if (pg != NULL && type == NULL && use_type == 1) { 782*1f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 783*1f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_NT_PREFIX, pg); 784*1f6eb021SLiane Praza } else if (pg != NULL && type == NULL) { 785*1f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 786*1f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_N_PREFIX, pg); 787*1f6eb021SLiane Praza } else if (type != NULL && pg == NULL) { 788*1f6eb021SLiane Praza size = snprintf(name, limit, "%s%s", 789*1f6eb021SLiane Praza SCF_PG_TM_PG_PATTERN_T_PREFIX, type); 790*1f6eb021SLiane Praza } else { 791*1f6eb021SLiane Praza assert(0); 792*1f6eb021SLiane Praza abort(); 793*1f6eb021SLiane Praza } 794*1f6eb021SLiane Praza 795*1f6eb021SLiane Praza if (size >= limit) { 796*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 797*1f6eb021SLiane Praza free(name); 798*1f6eb021SLiane Praza return (NULL); 799*1f6eb021SLiane Praza } else { 800*1f6eb021SLiane Praza return (name); 801*1f6eb021SLiane Praza } 802*1f6eb021SLiane Praza } 803*1f6eb021SLiane Praza 804*1f6eb021SLiane Praza /* 805*1f6eb021SLiane Praza * _scf_get_pg_name() 806*1f6eb021SLiane Praza * Gets the name of the supplied property group. On success, returns an 807*1f6eb021SLiane Praza * allocated string. The string must be freed by free(). 808*1f6eb021SLiane Praza * 809*1f6eb021SLiane Praza * Returns NULL on failure and sets scf_error() to _CONNECTION_BROKEN, 810*1f6eb021SLiane Praza * _DELETED, or _NO_MEMORY. 811*1f6eb021SLiane Praza */ 812*1f6eb021SLiane Praza static char * 813*1f6eb021SLiane Praza _scf_get_pg_name(scf_propertygroup_t *pg) 814*1f6eb021SLiane Praza { 815*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 816*1f6eb021SLiane Praza char *buf = malloc(sz); 817*1f6eb021SLiane Praza 818*1f6eb021SLiane Praza if (buf == NULL) { 819*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 820*1f6eb021SLiane Praza } else if (scf_pg_get_name(pg, buf, sz) == -1) { 821*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 822*1f6eb021SLiane Praza free(buf); 823*1f6eb021SLiane Praza buf = NULL; 824*1f6eb021SLiane Praza } else { 825*1f6eb021SLiane Praza assert(0); 826*1f6eb021SLiane Praza abort(); 827*1f6eb021SLiane Praza } 828*1f6eb021SLiane Praza } 829*1f6eb021SLiane Praza 830*1f6eb021SLiane Praza return (buf); 831*1f6eb021SLiane Praza } 832*1f6eb021SLiane Praza 833*1f6eb021SLiane Praza /* 834*1f6eb021SLiane Praza * char *_tmpl_prop_name() 835*1f6eb021SLiane Praza * 836*1f6eb021SLiane Praza * Returns the name of the property template prop (which is the name of 837*1f6eb021SLiane Praza * the property template property group) in the property group 838*1f6eb021SLiane Praza * template t. Returns NULL on failure and sets scf_error() to: 839*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 840*1f6eb021SLiane Praza * SCF_ERROR_DELETED 841*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 842*1f6eb021SLiane Praza * can't combine the arguments and get a reasonable length name 843*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 844*1f6eb021SLiane Praza */ 845*1f6eb021SLiane Praza static char * 846*1f6eb021SLiane Praza _tmpl_prop_name(const char *prop, scf_pg_tmpl_t *t) 847*1f6eb021SLiane Praza { 848*1f6eb021SLiane Praza char *name = NULL, *pg_name = NULL; 849*1f6eb021SLiane Praza size_t prefix_size; 850*1f6eb021SLiane Praza ssize_t limit, size = 0; 851*1f6eb021SLiane Praza 852*1f6eb021SLiane Praza assert(prop != NULL); 853*1f6eb021SLiane Praza assert(t->pt_pg != NULL); 854*1f6eb021SLiane Praza 855*1f6eb021SLiane Praza limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 856*1f6eb021SLiane Praza name = malloc(limit); 857*1f6eb021SLiane Praza if (name == NULL) { 858*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 859*1f6eb021SLiane Praza return (NULL); 860*1f6eb021SLiane Praza } 861*1f6eb021SLiane Praza 862*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(t->pt_pg)) == NULL) { 863*1f6eb021SLiane Praza free(name); 864*1f6eb021SLiane Praza return (NULL); 865*1f6eb021SLiane Praza } 866*1f6eb021SLiane Praza 867*1f6eb021SLiane Praza prefix_size = strlen(SCF_PG_TM_PG_PAT_BASE); 868*1f6eb021SLiane Praza if (strncmp(pg_name, SCF_PG_TM_PG_PAT_BASE, prefix_size) != 0) { 869*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 870*1f6eb021SLiane Praza free(name); 871*1f6eb021SLiane Praza free(pg_name); 872*1f6eb021SLiane Praza return (NULL); 873*1f6eb021SLiane Praza } 874*1f6eb021SLiane Praza 875*1f6eb021SLiane Praza size = snprintf(name, limit, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX, 876*1f6eb021SLiane Praza pg_name + prefix_size, prop); 877*1f6eb021SLiane Praza 878*1f6eb021SLiane Praza if (size >= limit) { 879*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 880*1f6eb021SLiane Praza free(name); 881*1f6eb021SLiane Praza free(pg_name); 882*1f6eb021SLiane Praza return (NULL); 883*1f6eb021SLiane Praza } else { 884*1f6eb021SLiane Praza free(pg_name); 885*1f6eb021SLiane Praza return (name); 886*1f6eb021SLiane Praza } 887*1f6eb021SLiane Praza } 888*1f6eb021SLiane Praza 889*1f6eb021SLiane Praza /* 890*1f6eb021SLiane Praza * int _get_snapshot() 891*1f6eb021SLiane Praza * 892*1f6eb021SLiane Praza * Gets the specified snapshot. If "snapshot" isn't defined, use the 893*1f6eb021SLiane Praza * running snapshot. If the snapshot isn't found, that may or may 894*1f6eb021SLiane Praza * not be an error depending on the caller. Return 0 in that case, 895*1f6eb021SLiane Praza * but leave scf_error() set to SCF_ERROR_NOT_FOUND. On all other 896*1f6eb021SLiane Praza * errors, set scf_error() to: 897*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 898*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 899*1f6eb021SLiane Praza * SCF_ERROR_DELETED 900*1f6eb021SLiane Praza * SCF_ERR_HANDLE_DESTROYED 901*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 902*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 903*1f6eb021SLiane Praza * The handle argument is NULL, or snaphot is not a valid snapshot name 904*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 905*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 906*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 907*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 908*1f6eb021SLiane Praza */ 909*1f6eb021SLiane Praza static int 910*1f6eb021SLiane Praza _get_snapshot(scf_instance_t *inst, const char *snapshot, 911*1f6eb021SLiane Praza scf_snapshot_t **snap) 912*1f6eb021SLiane Praza { 913*1f6eb021SLiane Praza int err; 914*1f6eb021SLiane Praza scf_handle_t *h; 915*1f6eb021SLiane Praza 916*1f6eb021SLiane Praza h = scf_instance_handle(inst); 917*1f6eb021SLiane Praza if (h == NULL) 918*1f6eb021SLiane Praza return (-1); 919*1f6eb021SLiane Praza 920*1f6eb021SLiane Praza if ((*snap = scf_snapshot_create(h)) == NULL) { 921*1f6eb021SLiane Praza return (-1); 922*1f6eb021SLiane Praza } 923*1f6eb021SLiane Praza 924*1f6eb021SLiane Praza /* Use running snapshot by default. */ 925*1f6eb021SLiane Praza if (snapshot == NULL) 926*1f6eb021SLiane Praza err = scf_instance_get_snapshot(inst, "running", *snap); 927*1f6eb021SLiane Praza else 928*1f6eb021SLiane Praza err = scf_instance_get_snapshot(inst, snapshot, *snap); 929*1f6eb021SLiane Praza 930*1f6eb021SLiane Praza if (err != 0) { 931*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 932*1f6eb021SLiane Praza scf_snapshot_destroy(*snap); 933*1f6eb021SLiane Praza *snap = NULL; 934*1f6eb021SLiane Praza return (-1); 935*1f6eb021SLiane Praza } else switch (scf_error()) { 936*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 937*1f6eb021SLiane Praza scf_snapshot_destroy(*snap); 938*1f6eb021SLiane Praza *snap = NULL; 939*1f6eb021SLiane Praza return (-1); 940*1f6eb021SLiane Praza 941*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 942*1f6eb021SLiane Praza scf_snapshot_destroy(*snap); 943*1f6eb021SLiane Praza *snap = NULL; 944*1f6eb021SLiane Praza return (0); 945*1f6eb021SLiane Praza 946*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 947*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 948*1f6eb021SLiane Praza default: 949*1f6eb021SLiane Praza assert(0); 950*1f6eb021SLiane Praza abort(); 951*1f6eb021SLiane Praza } 952*1f6eb021SLiane Praza } 953*1f6eb021SLiane Praza 954*1f6eb021SLiane Praza /* 955*1f6eb021SLiane Praza * Explicitly set SCF_ERROR_NONE so that the SCF_ERROR_NOT_FOUND 956*1f6eb021SLiane Praza * return above is explicitly guaranteed to be from 957*1f6eb021SLiane Praza * scf_instance_get_snapshot(). 958*1f6eb021SLiane Praza */ 959*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 960*1f6eb021SLiane Praza return (0); 961*1f6eb021SLiane Praza } 962*1f6eb021SLiane Praza 963*1f6eb021SLiane Praza /* 964*1f6eb021SLiane Praza * Returns NULL on error, sets scf_error() to: 965*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 966*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 967*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 968*1f6eb021SLiane Praza * The restarter's FMRI does not match an existing instance. 969*1f6eb021SLiane Praza * SCF_ERROR_DELETED 970*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 971*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 972*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 973*1f6eb021SLiane Praza * The restarter's FMRI is not a valid FMRI. 974*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 975*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 976*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 977*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 978*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 979*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 980*1f6eb021SLiane Praza * restarter property is not SCF_TYPE_ASTRING or has more than one value 981*1f6eb021SLiane Praza */ 982*1f6eb021SLiane Praza static scf_instance_t * 983*1f6eb021SLiane Praza _get_restarter_inst(scf_handle_t *h, scf_service_t *svc, 984*1f6eb021SLiane Praza scf_instance_t *inst, scf_snapshot_t *s) 985*1f6eb021SLiane Praza { 986*1f6eb021SLiane Praza char *restarter = NULL; 987*1f6eb021SLiane Praza scf_instance_t *ri = NULL; 988*1f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 989*1f6eb021SLiane Praza int ret = 0; 990*1f6eb021SLiane Praza 991*1f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 992*1f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 993*1f6eb021SLiane Praza 994*1f6eb021SLiane Praza if ((ri = scf_instance_create(h)) == NULL || 995*1f6eb021SLiane Praza (pg = scf_pg_create(h)) == NULL) { 996*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 997*1f6eb021SLiane Praza scf_instance_destroy(ri); 998*1f6eb021SLiane Praza return (NULL); 999*1f6eb021SLiane Praza } 1000*1f6eb021SLiane Praza 1001*1f6eb021SLiane Praza if (inst != NULL) 1002*1f6eb021SLiane Praza ret = scf_instance_get_pg_composed(inst, s, SCF_PG_GENERAL, 1003*1f6eb021SLiane Praza pg); 1004*1f6eb021SLiane Praza else 1005*1f6eb021SLiane Praza ret = scf_service_get_pg(svc, SCF_PG_GENERAL, pg); 1006*1f6eb021SLiane Praza 1007*1f6eb021SLiane Praza if (ret != 0) { 1008*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1009*1f6eb021SLiane Praza goto _get_restarter_inst_fail; 1010*1f6eb021SLiane Praza } else switch (scf_error()) { 1011*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1012*1f6eb021SLiane Praza /* Assume default restarter. */ 1013*1f6eb021SLiane Praza break; 1014*1f6eb021SLiane Praza 1015*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1016*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1017*1f6eb021SLiane Praza /* 1018*1f6eb021SLiane Praza * If the arguments to the above functions 1019*1f6eb021SLiane Praza * aren't derived from the same handle, there's 1020*1f6eb021SLiane Praza * something wrong with the internal implementation, 1021*1f6eb021SLiane Praza * not the public caller further up the chain. 1022*1f6eb021SLiane Praza */ 1023*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1024*1f6eb021SLiane Praza default: 1025*1f6eb021SLiane Praza assert(0); 1026*1f6eb021SLiane Praza abort(); 1027*1f6eb021SLiane Praza } 1028*1f6eb021SLiane Praza } else { 1029*1f6eb021SLiane Praza restarter = _scf_read_single_astring_from_pg(pg, 1030*1f6eb021SLiane Praza SCF_PROPERTY_RESTARTER); 1031*1f6eb021SLiane Praza /* zero length string is NOT a valid restarter */ 1032*1f6eb021SLiane Praza if (restarter != NULL && restarter[0] == '\0') { 1033*1f6eb021SLiane Praza free(restarter); 1034*1f6eb021SLiane Praza restarter = NULL; 1035*1f6eb021SLiane Praza } else if (restarter == NULL) { 1036*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1037*1f6eb021SLiane Praza goto _get_restarter_inst_fail; 1038*1f6eb021SLiane Praza } else switch (scf_error()) { 1039*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1040*1f6eb021SLiane Praza break; 1041*1f6eb021SLiane Praza 1042*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1043*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 1044*1f6eb021SLiane Praza (void) scf_set_error( 1045*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 1046*1f6eb021SLiane Praza goto _get_restarter_inst_fail; 1047*1f6eb021SLiane Praza 1048*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1049*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1050*1f6eb021SLiane Praza default: 1051*1f6eb021SLiane Praza assert(0); 1052*1f6eb021SLiane Praza abort(); 1053*1f6eb021SLiane Praza } 1054*1f6eb021SLiane Praza } 1055*1f6eb021SLiane Praza } 1056*1f6eb021SLiane Praza 1057*1f6eb021SLiane Praza if (restarter == NULL) { 1058*1f6eb021SLiane Praza /* Use default restarter */ 1059*1f6eb021SLiane Praza restarter = strdup(SCF_SERVICE_STARTD); 1060*1f6eb021SLiane Praza if (restarter == NULL) { 1061*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1062*1f6eb021SLiane Praza goto _get_restarter_inst_fail; 1063*1f6eb021SLiane Praza } 1064*1f6eb021SLiane Praza } 1065*1f6eb021SLiane Praza 1066*1f6eb021SLiane Praza if (scf_handle_decode_fmri(h, restarter, NULL, NULL, ri, NULL, NULL, 1067*1f6eb021SLiane Praza SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 1068*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1069*1f6eb021SLiane Praza uu_free(restarter); 1070*1f6eb021SLiane Praza goto _get_restarter_inst_fail; 1071*1f6eb021SLiane Praza } else switch (scf_error()) { 1072*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1073*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1074*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1075*1f6eb021SLiane Praza free(restarter); 1076*1f6eb021SLiane Praza goto _get_restarter_inst_fail; 1077*1f6eb021SLiane Praza 1078*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1079*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1080*1f6eb021SLiane Praza default: 1081*1f6eb021SLiane Praza assert(0); 1082*1f6eb021SLiane Praza abort(); 1083*1f6eb021SLiane Praza } 1084*1f6eb021SLiane Praza } 1085*1f6eb021SLiane Praza free(restarter); 1086*1f6eb021SLiane Praza scf_pg_destroy(pg); 1087*1f6eb021SLiane Praza 1088*1f6eb021SLiane Praza return (ri); 1089*1f6eb021SLiane Praza 1090*1f6eb021SLiane Praza _get_restarter_inst_fail: 1091*1f6eb021SLiane Praza scf_instance_destroy(ri); 1092*1f6eb021SLiane Praza scf_pg_destroy(pg); 1093*1f6eb021SLiane Praza return (NULL); 1094*1f6eb021SLiane Praza } 1095*1f6eb021SLiane Praza 1096*1f6eb021SLiane Praza /* 1097*1f6eb021SLiane Praza * Returns NULL on error, sets scf_error() to: 1098*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 1099*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 1100*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 1101*1f6eb021SLiane Praza * Restarter property has more than one value associated with it, 1102*1f6eb021SLiane Praza * or FMRI does not meet restrictions in scf_handle_decode_fmri() flags. 1103*1f6eb021SLiane Praza * SCF_ERROR_DELETED 1104*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 1105*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 1106*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 1107*1f6eb021SLiane Praza * The fmri argument in scf_handle_decode_fmri() is not a valid FMRI. 1108*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 1109*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 1110*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 1111*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 1112*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 1113*1f6eb021SLiane Praza */ 1114*1f6eb021SLiane Praza static scf_instance_t * 1115*1f6eb021SLiane Praza _get_global_inst(scf_handle_t *h) 1116*1f6eb021SLiane Praza { 1117*1f6eb021SLiane Praza scf_instance_t *ri; 1118*1f6eb021SLiane Praza 1119*1f6eb021SLiane Praza if ((ri = scf_instance_create(h)) == NULL) { 1120*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 1121*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_RESOURCES); 1122*1f6eb021SLiane Praza return (NULL); 1123*1f6eb021SLiane Praza } 1124*1f6eb021SLiane Praza 1125*1f6eb021SLiane Praza if (scf_handle_decode_fmri(h, SCF_INSTANCE_GLOBAL, NULL, NULL, ri, 1126*1f6eb021SLiane Praza NULL, NULL, 1127*1f6eb021SLiane Praza SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 1128*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1129*1f6eb021SLiane Praza scf_instance_destroy(ri); 1130*1f6eb021SLiane Praza return (NULL); 1131*1f6eb021SLiane Praza } else switch (scf_error()) { 1132*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1133*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1134*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1135*1f6eb021SLiane Praza scf_instance_destroy(ri); 1136*1f6eb021SLiane Praza return (NULL); 1137*1f6eb021SLiane Praza 1138*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1139*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1140*1f6eb021SLiane Praza default: 1141*1f6eb021SLiane Praza assert(0); 1142*1f6eb021SLiane Praza abort(); 1143*1f6eb021SLiane Praza } 1144*1f6eb021SLiane Praza } 1145*1f6eb021SLiane Praza 1146*1f6eb021SLiane Praza return (ri); 1147*1f6eb021SLiane Praza } 1148*1f6eb021SLiane Praza 1149*1f6eb021SLiane Praza /* 1150*1f6eb021SLiane Praza * Call the supplied function for each of the service or instance, the 1151*1f6eb021SLiane Praza * service's restarter, and the globally defined template instance. 1152*1f6eb021SLiane Praza * If the function returns SCF_WALK_ERROR, the walk is ended. If 1153*1f6eb021SLiane Praza * the function returns SCF_WALK_NEXT, the next entity is tried. 1154*1f6eb021SLiane Praza * 1155*1f6eb021SLiane Praza * The function is only expected to return SCF_WALK_DONE if it has 1156*1f6eb021SLiane Praza * found a property group match in the current entity, and has 1157*1f6eb021SLiane Praza * populated p->pw_pg with the matching property group. 1158*1f6eb021SLiane Praza */ 1159*1f6eb021SLiane Praza static void 1160*1f6eb021SLiane Praza _walk_template_instances(scf_service_t *svc, scf_instance_t *inst, 1161*1f6eb021SLiane Praza scf_snapshot_t *snap, walk_template_inst_func_t *func, 1162*1f6eb021SLiane Praza pg_tmpl_walk_t *p, int flag) 1163*1f6eb021SLiane Praza { 1164*1f6eb021SLiane Praza scf_instance_t *tmpl_inst = NULL; 1165*1f6eb021SLiane Praza scf_handle_t *h; 1166*1f6eb021SLiane Praza int ret; 1167*1f6eb021SLiane Praza char *tg = NULL; 1168*1f6eb021SLiane Praza 1169*1f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 1170*1f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 1171*1f6eb021SLiane Praza 1172*1f6eb021SLiane Praza if (inst != NULL) 1173*1f6eb021SLiane Praza h = scf_instance_handle(inst); 1174*1f6eb021SLiane Praza else 1175*1f6eb021SLiane Praza h = scf_service_handle(svc); 1176*1f6eb021SLiane Praza if (h == NULL) 1177*1f6eb021SLiane Praza goto done; 1178*1f6eb021SLiane Praza 1179*1f6eb021SLiane Praza /* First, use supplied service or instance */ 1180*1f6eb021SLiane Praza p->pw_target = SCF_TM_TARGET_THIS; 1181*1f6eb021SLiane Praza ret = func(svc, inst, p); 1182*1f6eb021SLiane Praza switch (ret) { 1183*1f6eb021SLiane Praza case SCF_WALK_NEXT: 1184*1f6eb021SLiane Praza break; 1185*1f6eb021SLiane Praza case SCF_WALK_DONE: 1186*1f6eb021SLiane Praza /* 1187*1f6eb021SLiane Praza * Check that the template scoping matches and if not, 1188*1f6eb021SLiane Praza * continue. 1189*1f6eb021SLiane Praza */ 1190*1f6eb021SLiane Praza assert(p->pw_pg != NULL); 1191*1f6eb021SLiane Praza tg = _scf_read_single_astring_from_pg(p->pw_pg, 1192*1f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 1193*1f6eb021SLiane Praza if (tg == NULL || /* scf_error() was set */ 1194*1f6eb021SLiane Praza (strcmp(tg, SCF_TM_TARGET_INSTANCE) != 0 && 1195*1f6eb021SLiane Praza strcmp(tg, SCF_TM_TARGET_THIS) != 0 && 1196*1f6eb021SLiane Praza (flag & SCF_PG_TMPL_FLAG_EXACT) != 1197*1f6eb021SLiane Praza SCF_PG_TMPL_FLAG_EXACT)) { 1198*1f6eb021SLiane Praza scf_pg_destroy(p->pw_pg); 1199*1f6eb021SLiane Praza p->pw_pg = NULL; 1200*1f6eb021SLiane Praza if (tg != NULL) { 1201*1f6eb021SLiane Praza free(tg); 1202*1f6eb021SLiane Praza tg = NULL; 1203*1f6eb021SLiane Praza break; 1204*1f6eb021SLiane Praza } 1205*1f6eb021SLiane Praza } 1206*1f6eb021SLiane Praza /*FALLTHROUGH*/ 1207*1f6eb021SLiane Praza case SCF_WALK_ERROR: 1208*1f6eb021SLiane Praza goto done; 1209*1f6eb021SLiane Praza /*NOTREACHED*/ 1210*1f6eb021SLiane Praza default: 1211*1f6eb021SLiane Praza assert(0); 1212*1f6eb021SLiane Praza abort(); 1213*1f6eb021SLiane Praza } 1214*1f6eb021SLiane Praza 1215*1f6eb021SLiane Praza /* Next the restarter. */ 1216*1f6eb021SLiane Praza p->pw_target = SCF_TM_TARGET_DELEGATE; 1217*1f6eb021SLiane Praza tmpl_inst = _get_restarter_inst(h, svc, inst, snap); 1218*1f6eb021SLiane Praza if (tmpl_inst != NULL) { 1219*1f6eb021SLiane Praza ret = func(NULL, tmpl_inst, p); 1220*1f6eb021SLiane Praza switch (ret) { 1221*1f6eb021SLiane Praza case SCF_WALK_NEXT: 1222*1f6eb021SLiane Praza break; 1223*1f6eb021SLiane Praza case SCF_WALK_DONE: 1224*1f6eb021SLiane Praza /* 1225*1f6eb021SLiane Praza * Check that the template scoping matches and if not, 1226*1f6eb021SLiane Praza * continue. 1227*1f6eb021SLiane Praza */ 1228*1f6eb021SLiane Praza assert(p->pw_pg != NULL); 1229*1f6eb021SLiane Praza tg = _scf_read_single_astring_from_pg(p->pw_pg, 1230*1f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 1231*1f6eb021SLiane Praza if (tg == NULL || /* scf_error() was set */ 1232*1f6eb021SLiane Praza strcmp(tg, SCF_TM_TARGET_DELEGATE) != 0) { 1233*1f6eb021SLiane Praza scf_pg_destroy(p->pw_pg); 1234*1f6eb021SLiane Praza p->pw_pg = NULL; 1235*1f6eb021SLiane Praza if (tg != NULL) { 1236*1f6eb021SLiane Praza free(tg); 1237*1f6eb021SLiane Praza tg = NULL; 1238*1f6eb021SLiane Praza break; 1239*1f6eb021SLiane Praza } 1240*1f6eb021SLiane Praza } 1241*1f6eb021SLiane Praza /*FALLTHROUGH*/ 1242*1f6eb021SLiane Praza case SCF_WALK_ERROR: 1243*1f6eb021SLiane Praza goto done; 1244*1f6eb021SLiane Praza /*NOTREACHED*/ 1245*1f6eb021SLiane Praza default: 1246*1f6eb021SLiane Praza assert(0); 1247*1f6eb021SLiane Praza abort(); 1248*1f6eb021SLiane Praza } 1249*1f6eb021SLiane Praza } 1250*1f6eb021SLiane Praza 1251*1f6eb021SLiane Praza p->pw_target = SCF_TM_TARGET_ALL; 1252*1f6eb021SLiane Praza scf_instance_destroy(tmpl_inst); 1253*1f6eb021SLiane Praza tmpl_inst = _get_global_inst(h); 1254*1f6eb021SLiane Praza if (tmpl_inst != NULL) { 1255*1f6eb021SLiane Praza ret = func(NULL, tmpl_inst, p); 1256*1f6eb021SLiane Praza switch (ret) { 1257*1f6eb021SLiane Praza case SCF_WALK_NEXT: 1258*1f6eb021SLiane Praza break; 1259*1f6eb021SLiane Praza case SCF_WALK_DONE: 1260*1f6eb021SLiane Praza /* 1261*1f6eb021SLiane Praza * Check that the template scoping matches and if not, 1262*1f6eb021SLiane Praza * continue. 1263*1f6eb021SLiane Praza */ 1264*1f6eb021SLiane Praza assert(p->pw_pg != NULL); 1265*1f6eb021SLiane Praza tg = _scf_read_single_astring_from_pg(p->pw_pg, 1266*1f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 1267*1f6eb021SLiane Praza if (tg == NULL || /* scf_error() was set */ 1268*1f6eb021SLiane Praza strcmp(tg, SCF_TM_TARGET_ALL) != 0) { 1269*1f6eb021SLiane Praza scf_pg_destroy(p->pw_pg); 1270*1f6eb021SLiane Praza p->pw_pg = NULL; 1271*1f6eb021SLiane Praza if (tg != NULL) { 1272*1f6eb021SLiane Praza free(tg); 1273*1f6eb021SLiane Praza tg = NULL; 1274*1f6eb021SLiane Praza break; 1275*1f6eb021SLiane Praza } 1276*1f6eb021SLiane Praza } 1277*1f6eb021SLiane Praza /*FALLTHROUGH*/ 1278*1f6eb021SLiane Praza case SCF_WALK_ERROR: 1279*1f6eb021SLiane Praza goto done; 1280*1f6eb021SLiane Praza /*NOTREACHED*/ 1281*1f6eb021SLiane Praza default: 1282*1f6eb021SLiane Praza assert(0); 1283*1f6eb021SLiane Praza abort(); 1284*1f6eb021SLiane Praza } 1285*1f6eb021SLiane Praza } 1286*1f6eb021SLiane Praza 1287*1f6eb021SLiane Praza done: 1288*1f6eb021SLiane Praza free(tg); 1289*1f6eb021SLiane Praza if (ret != SCF_WALK_DONE) 1290*1f6eb021SLiane Praza scf_instance_destroy(tmpl_inst); 1291*1f6eb021SLiane Praza p->pw_target = NULL; 1292*1f6eb021SLiane Praza } 1293*1f6eb021SLiane Praza 1294*1f6eb021SLiane Praza /* 1295*1f6eb021SLiane Praza * _get_pg() returns 0 on success and -1 on failure. Sets scf_error() 1296*1f6eb021SLiane Praza * on failure. 1297*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 1298*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 1299*1f6eb021SLiane Praza * SCF_ERROR_DELETED 1300*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_MISMATCH 1301*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 1302*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 1303*1f6eb021SLiane Praza * name is not a valid property group. 1304*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 1305*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 1306*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 1307*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 1308*1f6eb021SLiane Praza */ 1309*1f6eb021SLiane Praza static int 1310*1f6eb021SLiane Praza _get_pg(scf_service_t *svc, scf_instance_t *inst, 1311*1f6eb021SLiane Praza const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg) 1312*1f6eb021SLiane Praza { 1313*1f6eb021SLiane Praza int ret; 1314*1f6eb021SLiane Praza 1315*1f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 1316*1f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 1317*1f6eb021SLiane Praza assert(pg != NULL); 1318*1f6eb021SLiane Praza 1319*1f6eb021SLiane Praza if (inst != NULL) 1320*1f6eb021SLiane Praza ret = scf_instance_get_pg_composed(inst, snap, name, pg); 1321*1f6eb021SLiane Praza else 1322*1f6eb021SLiane Praza ret = scf_service_get_pg(svc, name, pg); 1323*1f6eb021SLiane Praza 1324*1f6eb021SLiane Praza return (ret); 1325*1f6eb021SLiane Praza } 1326*1f6eb021SLiane Praza 1327*1f6eb021SLiane Praza /* 1328*1f6eb021SLiane Praza * Returns SCF_WALK_NEXT for not found, SCF_WALK_ERROR for error, 1329*1f6eb021SLiane Praza * and SCF_WALK_DONE for found. 1330*1f6eb021SLiane Praza * On error, destroy pg and set it to NULL. 1331*1f6eb021SLiane Praza * 1332*1f6eb021SLiane Praza * Sets scf_error() if SCF_WALK_ERROR is returned to _BACKEND_ACCESS, 1333*1f6eb021SLiane Praza * _CONNECTION_BROKEN, _INTERNAL, _INVALID_ARGUMENT (name is not a 1334*1f6eb021SLiane Praza * valid property group), _NO_RESOURCES, or _NOT_BOUND. 1335*1f6eb021SLiane Praza */ 1336*1f6eb021SLiane Praza static int 1337*1f6eb021SLiane Praza _lookup_pg(scf_service_t *svc, scf_instance_t *inst, 1338*1f6eb021SLiane Praza const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg) 1339*1f6eb021SLiane Praza { 1340*1f6eb021SLiane Praza int ret; 1341*1f6eb021SLiane Praza 1342*1f6eb021SLiane Praza ret = _get_pg(svc, inst, snap, name, pg); 1343*1f6eb021SLiane Praza 1344*1f6eb021SLiane Praza if (ret == 0) { 1345*1f6eb021SLiane Praza return (SCF_WALK_DONE); 1346*1f6eb021SLiane Praza } else { 1347*1f6eb021SLiane Praza switch (scf_error()) { 1348*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1349*1f6eb021SLiane Praza case SCF_ERROR_DELETED: 1350*1f6eb021SLiane Praza return (SCF_WALK_NEXT); 1351*1f6eb021SLiane Praza 1352*1f6eb021SLiane Praza case SCF_ERROR_BACKEND_ACCESS: 1353*1f6eb021SLiane Praza case SCF_ERROR_CONNECTION_BROKEN: 1354*1f6eb021SLiane Praza case SCF_ERROR_INTERNAL: 1355*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1356*1f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 1357*1f6eb021SLiane Praza case SCF_ERROR_NO_RESOURCES: 1358*1f6eb021SLiane Praza scf_pg_destroy(pg); 1359*1f6eb021SLiane Praza pg = NULL; 1360*1f6eb021SLiane Praza return (SCF_WALK_ERROR); 1361*1f6eb021SLiane Praza 1362*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1363*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1364*1f6eb021SLiane Praza default: 1365*1f6eb021SLiane Praza assert(0); 1366*1f6eb021SLiane Praza abort(); 1367*1f6eb021SLiane Praza } 1368*1f6eb021SLiane Praza } 1369*1f6eb021SLiane Praza 1370*1f6eb021SLiane Praza /*NOTREACHED*/ 1371*1f6eb021SLiane Praza } 1372*1f6eb021SLiane Praza 1373*1f6eb021SLiane Praza /* 1374*1f6eb021SLiane Praza * If match, return 0. If no match, return 1. If error, return -1. 1375*1f6eb021SLiane Praza * On error set scf_error() to _BACKEND_ACCESS, _CONNECTION_BROKEN, 1376*1f6eb021SLiane Praza * _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, _NO_RESOURCES, _NOT_BOUND, 1377*1f6eb021SLiane Praza * _NOT_SET (property group specified by pg is not set), _PERMISSION_DENIED, 1378*1f6eb021SLiane Praza * or _TEMPLATE_INVALID (target property is not SCF_TYPE_ASTRING or has 1379*1f6eb021SLiane Praza * more than one value). 1380*1f6eb021SLiane Praza */ 1381*1f6eb021SLiane Praza static int 1382*1f6eb021SLiane Praza check_target_match(scf_propertygroup_t *pg, const char *target) 1383*1f6eb021SLiane Praza { 1384*1f6eb021SLiane Praza char *pg_target; 1385*1f6eb021SLiane Praza int ret = 0; 1386*1f6eb021SLiane Praza 1387*1f6eb021SLiane Praza pg_target = _scf_read_single_astring_from_pg(pg, 1388*1f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 1389*1f6eb021SLiane Praza if (pg_target == NULL) { 1390*1f6eb021SLiane Praza switch (scf_error()) { 1391*1f6eb021SLiane Praza case SCF_ERROR_DELETED: 1392*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1393*1f6eb021SLiane Praza return (1); 1394*1f6eb021SLiane Praza 1395*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1396*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 1397*1f6eb021SLiane Praza (void) scf_set_error( 1398*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 1399*1f6eb021SLiane Praza /*FALLTHROUGH*/ 1400*1f6eb021SLiane Praza 1401*1f6eb021SLiane Praza case SCF_ERROR_BACKEND_ACCESS: 1402*1f6eb021SLiane Praza case SCF_ERROR_CONNECTION_BROKEN: 1403*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_DESTROYED: 1404*1f6eb021SLiane Praza case SCF_ERROR_INTERNAL: 1405*1f6eb021SLiane Praza case SCF_ERROR_NO_RESOURCES: 1406*1f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 1407*1f6eb021SLiane Praza case SCF_ERROR_PERMISSION_DENIED: 1408*1f6eb021SLiane Praza return (-1); 1409*1f6eb021SLiane Praza 1410*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1411*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1412*1f6eb021SLiane Praza default: 1413*1f6eb021SLiane Praza assert(0); 1414*1f6eb021SLiane Praza abort(); 1415*1f6eb021SLiane Praza } 1416*1f6eb021SLiane Praza /*NOTREACHED*/ 1417*1f6eb021SLiane Praza } 1418*1f6eb021SLiane Praza 1419*1f6eb021SLiane Praza /* For a desired target of 'this', check for 'this' and 'instance'. */ 1420*1f6eb021SLiane Praza if ((strcmp(target, SCF_TM_TARGET_INSTANCE) == 0 || 1421*1f6eb021SLiane Praza strcmp(target, SCF_TM_TARGET_THIS) == 0) && 1422*1f6eb021SLiane Praza (strcmp(pg_target, SCF_TM_TARGET_INSTANCE) == 0 || 1423*1f6eb021SLiane Praza strcmp(pg_target, SCF_TM_TARGET_THIS) == 0)) { 1424*1f6eb021SLiane Praza goto cleanup; 1425*1f6eb021SLiane Praza } 1426*1f6eb021SLiane Praza 1427*1f6eb021SLiane Praza if (strcmp(target, SCF_TM_TARGET_DELEGATE) == 0 && 1428*1f6eb021SLiane Praza strcmp(pg_target, SCF_TM_TARGET_DELEGATE) == 0) { 1429*1f6eb021SLiane Praza goto cleanup; 1430*1f6eb021SLiane Praza } 1431*1f6eb021SLiane Praza 1432*1f6eb021SLiane Praza if (strcmp(target, SCF_TM_TARGET_ALL) == 0 && 1433*1f6eb021SLiane Praza strcmp(pg_target, SCF_TM_TARGET_ALL) == 0) { 1434*1f6eb021SLiane Praza goto cleanup; 1435*1f6eb021SLiane Praza } 1436*1f6eb021SLiane Praza 1437*1f6eb021SLiane Praza ret = 1; 1438*1f6eb021SLiane Praza cleanup: 1439*1f6eb021SLiane Praza free(pg_target); 1440*1f6eb021SLiane Praza return (ret); 1441*1f6eb021SLiane Praza } 1442*1f6eb021SLiane Praza 1443*1f6eb021SLiane Praza /* 1444*1f6eb021SLiane Praza * Check if a matching template property group exists for each of: 1445*1f6eb021SLiane Praza * name and type, name only, type only, and completely wildcarded 1446*1f6eb021SLiane Praza * template. 1447*1f6eb021SLiane Praza * 1448*1f6eb021SLiane Praza * Both pg_name and pg_type are optional. 1449*1f6eb021SLiane Praza * 1450*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error(): 1451*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 1452*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 1453*1f6eb021SLiane Praza * SCF_ERROR_DELETED 1454*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 1455*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 1456*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 1457*1f6eb021SLiane Praza * can't combine the _tmpl_pg_name arguments and get a reasonable 1458*1f6eb021SLiane Praza * length name, or pg_name is not a valid property group. 1459*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 1460*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 1461*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 1462*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 1463*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 1464*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 1465*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 1466*1f6eb021SLiane Praza * target property is not SCF_TYPE_ASTRING or has more than one value. 1467*1f6eb021SLiane Praza */ 1468*1f6eb021SLiane Praza static scf_propertygroup_t * 1469*1f6eb021SLiane Praza _find_template_pg_match(scf_service_t *svc, scf_instance_t *inst, 1470*1f6eb021SLiane Praza const scf_snapshot_t *snap, const char *pg_name, const char *pg_type, 1471*1f6eb021SLiane Praza const char *target, char **tmpl_pg_name) 1472*1f6eb021SLiane Praza { 1473*1f6eb021SLiane Praza int ret, r; 1474*1f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 1475*1f6eb021SLiane Praza scf_handle_t *h; 1476*1f6eb021SLiane Praza scf_iter_t *iter; 1477*1f6eb021SLiane Praza char *name, *type; 1478*1f6eb021SLiane Praza 1479*1f6eb021SLiane Praza assert(inst != NULL || svc != NULL); 1480*1f6eb021SLiane Praza assert(inst == NULL || svc == NULL); 1481*1f6eb021SLiane Praza 1482*1f6eb021SLiane Praza if (inst != NULL) 1483*1f6eb021SLiane Praza h = scf_instance_handle(inst); 1484*1f6eb021SLiane Praza else 1485*1f6eb021SLiane Praza h = scf_service_handle(svc); 1486*1f6eb021SLiane Praza if (h == NULL) { 1487*1f6eb021SLiane Praza return (NULL); 1488*1f6eb021SLiane Praza } 1489*1f6eb021SLiane Praza 1490*1f6eb021SLiane Praza if ((pg = scf_pg_create(h)) == NULL || 1491*1f6eb021SLiane Praza (iter = scf_iter_create(h)) == NULL) { 1492*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 1493*1f6eb021SLiane Praza scf_pg_destroy(pg); 1494*1f6eb021SLiane Praza return (NULL); 1495*1f6eb021SLiane Praza } 1496*1f6eb021SLiane Praza 1497*1f6eb021SLiane Praza /* 1498*1f6eb021SLiane Praza * We're going to walk through the possible pg templates that 1499*1f6eb021SLiane Praza * could match the supplied name and type. We do this 1500*1f6eb021SLiane Praza * by explicit name lookups when possible to avoid having to 1501*1f6eb021SLiane Praza * keep track of a most-explicit-match during iteration. 1502*1f6eb021SLiane Praza */ 1503*1f6eb021SLiane Praza 1504*1f6eb021SLiane Praza /* First look for a template with name and type set and matching. */ 1505*1f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(pg_name, pg_type, 1); 1506*1f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 1507*1f6eb021SLiane Praza goto fail; 1508*1f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 1509*1f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 1510*1f6eb021SLiane Praza if (pg != NULL) { 1511*1f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 1512*1f6eb021SLiane Praza goto done; 1513*1f6eb021SLiane Praza else if (r == -1) 1514*1f6eb021SLiane Praza goto fail; 1515*1f6eb021SLiane Praza } else { 1516*1f6eb021SLiane Praza goto done; 1517*1f6eb021SLiane Praza } 1518*1f6eb021SLiane Praza } 1519*1f6eb021SLiane Praza free(*tmpl_pg_name); 1520*1f6eb021SLiane Praza 1521*1f6eb021SLiane Praza /* 1522*1f6eb021SLiane Praza * Need to search on a name-only match before searching on 1523*1f6eb021SLiane Praza * type matches. 1524*1f6eb021SLiane Praza */ 1525*1f6eb021SLiane Praza 1526*1f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(pg_name, NULL, 0); 1527*1f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 1528*1f6eb021SLiane Praza goto fail; 1529*1f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 1530*1f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 1531*1f6eb021SLiane Praza if (pg != NULL) { 1532*1f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 1533*1f6eb021SLiane Praza goto done; 1534*1f6eb021SLiane Praza else if (r == -1) 1535*1f6eb021SLiane Praza goto fail; 1536*1f6eb021SLiane Praza } else { 1537*1f6eb021SLiane Praza goto done; 1538*1f6eb021SLiane Praza } 1539*1f6eb021SLiane Praza } 1540*1f6eb021SLiane Praza free(*tmpl_pg_name); 1541*1f6eb021SLiane Praza 1542*1f6eb021SLiane Praza /* Next, see if there's an "nt" template where the type matches. */ 1543*1f6eb021SLiane Praza if (pg_type != NULL && pg_name == NULL) { 1544*1f6eb021SLiane Praza if (inst != NULL) 1545*1f6eb021SLiane Praza ret = scf_iter_instance_pgs_typed_composed(iter, inst, 1546*1f6eb021SLiane Praza snap, SCF_GROUP_TEMPLATE_PG_PATTERN); 1547*1f6eb021SLiane Praza else 1548*1f6eb021SLiane Praza ret = scf_iter_service_pgs_typed(iter, svc, 1549*1f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN); 1550*1f6eb021SLiane Praza 1551*1f6eb021SLiane Praza if (ret != 0) { 1552*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1553*1f6eb021SLiane Praza goto fail; 1554*1f6eb021SLiane Praza } else { 1555*1f6eb021SLiane Praza assert(0); 1556*1f6eb021SLiane Praza abort(); 1557*1f6eb021SLiane Praza } 1558*1f6eb021SLiane Praza } 1559*1f6eb021SLiane Praza 1560*1f6eb021SLiane Praza while ((ret = scf_iter_next_pg(iter, pg)) == 1) { 1561*1f6eb021SLiane Praza /* Make sure this is a name and type specified pg. */ 1562*1f6eb021SLiane Praza name = _scf_read_single_astring_from_pg(pg, 1563*1f6eb021SLiane Praza SCF_PROPERTY_TM_NAME); 1564*1f6eb021SLiane Praza if (name == NULL) 1565*1f6eb021SLiane Praza continue; 1566*1f6eb021SLiane Praza type = _scf_read_single_astring_from_pg(pg, 1567*1f6eb021SLiane Praza SCF_PROPERTY_TM_TYPE); 1568*1f6eb021SLiane Praza if (type == NULL) { 1569*1f6eb021SLiane Praza free(name); 1570*1f6eb021SLiane Praza continue; 1571*1f6eb021SLiane Praza } 1572*1f6eb021SLiane Praza if (strcmp(pg_type, type) == 0 && 1573*1f6eb021SLiane Praza check_target_match(pg, target) == 0) { 1574*1f6eb021SLiane Praza *tmpl_pg_name = name; 1575*1f6eb021SLiane Praza free(type); 1576*1f6eb021SLiane Praza goto done; 1577*1f6eb021SLiane Praza } 1578*1f6eb021SLiane Praza free(type); 1579*1f6eb021SLiane Praza free(name); 1580*1f6eb021SLiane Praza } 1581*1f6eb021SLiane Praza if (ret == -1) { 1582*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1583*1f6eb021SLiane Praza goto fail; 1584*1f6eb021SLiane Praza } else { 1585*1f6eb021SLiane Praza assert(0); 1586*1f6eb021SLiane Praza abort(); 1587*1f6eb021SLiane Praza } 1588*1f6eb021SLiane Praza } 1589*1f6eb021SLiane Praza } 1590*1f6eb021SLiane Praza 1591*1f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(NULL, pg_type, 0); 1592*1f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 1593*1f6eb021SLiane Praza goto fail; 1594*1f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 1595*1f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 1596*1f6eb021SLiane Praza if (pg != NULL) { 1597*1f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 1598*1f6eb021SLiane Praza goto done; 1599*1f6eb021SLiane Praza else if (r == -1) 1600*1f6eb021SLiane Praza goto fail; 1601*1f6eb021SLiane Praza } else { 1602*1f6eb021SLiane Praza goto done; 1603*1f6eb021SLiane Praza } 1604*1f6eb021SLiane Praza } 1605*1f6eb021SLiane Praza free(*tmpl_pg_name); 1606*1f6eb021SLiane Praza 1607*1f6eb021SLiane Praza *tmpl_pg_name = _tmpl_pg_name(NULL, NULL, 0); 1608*1f6eb021SLiane Praza if (*tmpl_pg_name == NULL) 1609*1f6eb021SLiane Praza goto fail; 1610*1f6eb021SLiane Praza ret = _lookup_pg(svc, inst, snap, *tmpl_pg_name, pg); 1611*1f6eb021SLiane Praza if (ret != SCF_WALK_NEXT) { 1612*1f6eb021SLiane Praza if (pg != NULL) { 1613*1f6eb021SLiane Praza if ((r = check_target_match(pg, target)) == 0) 1614*1f6eb021SLiane Praza goto done; 1615*1f6eb021SLiane Praza else if (r == -1) 1616*1f6eb021SLiane Praza goto fail; 1617*1f6eb021SLiane Praza } else { 1618*1f6eb021SLiane Praza goto done; 1619*1f6eb021SLiane Praza } 1620*1f6eb021SLiane Praza } 1621*1f6eb021SLiane Praza 1622*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 1623*1f6eb021SLiane Praza fail: 1624*1f6eb021SLiane Praza scf_pg_destroy(pg); 1625*1f6eb021SLiane Praza if (*tmpl_pg_name != NULL) 1626*1f6eb021SLiane Praza free(*tmpl_pg_name); 1627*1f6eb021SLiane Praza *tmpl_pg_name = NULL; 1628*1f6eb021SLiane Praza pg = NULL; 1629*1f6eb021SLiane Praza done: 1630*1f6eb021SLiane Praza if (ret == SCF_WALK_ERROR) 1631*1f6eb021SLiane Praza free(*tmpl_pg_name); 1632*1f6eb021SLiane Praza scf_iter_destroy(iter); 1633*1f6eb021SLiane Praza return (pg); 1634*1f6eb021SLiane Praza } 1635*1f6eb021SLiane Praza 1636*1f6eb021SLiane Praza /* 1637*1f6eb021SLiane Praza * Finds the pg match in either the supplied service or instance. 1638*1f6eb021SLiane Praza * Returns SCF_WALK_ERROR, SCF_WALK_NEXT, or SCF_WALK_DONE. 1639*1f6eb021SLiane Praza * If returning SCF_WALK_ERROR, sets scf_error(): 1640*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 1641*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 1642*1f6eb021SLiane Praza * SCF_ERROR_DELETED 1643*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 1644*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 1645*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 1646*1f6eb021SLiane Praza * The snaphot is not a valid snapshot name, 1647*1f6eb021SLiane Praza * or can't create a reasonable property group template name. 1648*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 1649*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 1650*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 1651*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 1652*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 1653*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 1654*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 1655*1f6eb021SLiane Praza * target property is not SCF_TYPE_ASTRING or has more than one value. 1656*1f6eb021SLiane Praza */ 1657*1f6eb021SLiane Praza static int 1658*1f6eb021SLiane Praza find_pg_match(scf_service_t *svc, scf_instance_t *inst, pg_tmpl_walk_t *p) 1659*1f6eb021SLiane Praza { 1660*1f6eb021SLiane Praza scf_snapshot_t *tmpl_snap = NULL; 1661*1f6eb021SLiane Praza scf_propertygroup_t *pg; 1662*1f6eb021SLiane Praza scf_handle_t *h; 1663*1f6eb021SLiane Praza char *tmpl_pg_name; 1664*1f6eb021SLiane Praza 1665*1f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 1666*1f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 1667*1f6eb021SLiane Praza 1668*1f6eb021SLiane Praza if (inst != NULL) 1669*1f6eb021SLiane Praza h = scf_instance_handle(inst); 1670*1f6eb021SLiane Praza else 1671*1f6eb021SLiane Praza h = scf_service_handle(svc); 1672*1f6eb021SLiane Praza if (h == NULL) 1673*1f6eb021SLiane Praza return (SCF_WALK_ERROR); 1674*1f6eb021SLiane Praza 1675*1f6eb021SLiane Praza if (p->pw_snapname != NULL) { 1676*1f6eb021SLiane Praza if (_get_snapshot(inst, p->pw_snapname, &tmpl_snap) == -1) 1677*1f6eb021SLiane Praza return (SCF_WALK_ERROR); 1678*1f6eb021SLiane Praza } 1679*1f6eb021SLiane Praza pg = _find_template_pg_match(svc, inst, tmpl_snap, p->pw_pgname, 1680*1f6eb021SLiane Praza p->pw_pgtype, p->pw_target, &tmpl_pg_name); 1681*1f6eb021SLiane Praza 1682*1f6eb021SLiane Praza if (pg != NULL) { 1683*1f6eb021SLiane Praza p->pw_snap = tmpl_snap; 1684*1f6eb021SLiane Praza p->pw_pg = pg; 1685*1f6eb021SLiane Praza p->pw_tmpl_pgname = tmpl_pg_name; 1686*1f6eb021SLiane Praza p->pw_inst = inst; 1687*1f6eb021SLiane Praza p->pw_svc = svc; 1688*1f6eb021SLiane Praza return (SCF_WALK_DONE); 1689*1f6eb021SLiane Praza } 1690*1f6eb021SLiane Praza 1691*1f6eb021SLiane Praza scf_snapshot_destroy(tmpl_snap); 1692*1f6eb021SLiane Praza return (SCF_WALK_NEXT); 1693*1f6eb021SLiane Praza } 1694*1f6eb021SLiane Praza 1695*1f6eb021SLiane Praza /* 1696*1f6eb021SLiane Praza * return 0 on success and -1 on failure. 1697*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 1698*1f6eb021SLiane Praza * SCF_ERROR_DELETED 1699*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 1700*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_MISMATCH 1701*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 1702*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 1703*1f6eb021SLiane Praza * FMRI argument, snapshot name, pg_name, or pg is invalid. 1704*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 1705*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 1706*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 1707*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 1708*1f6eb021SLiane Praza * SCF_ERROR_NOT_SET 1709*1f6eb021SLiane Praza */ 1710*1f6eb021SLiane Praza int 1711*1f6eb021SLiane Praza scf_tmpl_get_by_pg(scf_propertygroup_t *pg, scf_pg_tmpl_t *pg_tmpl, int flags) 1712*1f6eb021SLiane Praza { 1713*1f6eb021SLiane Praza char *fmribuf = NULL, *snapbuf = NULL, *pg_name = NULL, *pg_type = NULL; 1714*1f6eb021SLiane Praza int ret = 0; 1715*1f6eb021SLiane Praza ssize_t fbufsz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1; 1716*1f6eb021SLiane Praza ssize_t nbufsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 1717*1f6eb021SLiane Praza ssize_t tbufsz = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1; 1718*1f6eb021SLiane Praza scf_instance_t *inst = NULL; 1719*1f6eb021SLiane Praza scf_snaplevel_t *snaplvl = NULL; 1720*1f6eb021SLiane Praza scf_service_t *svc = NULL; 1721*1f6eb021SLiane Praza scf_handle_t *h; 1722*1f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 1723*1f6eb021SLiane Praza pg_tmpl_walk_t *p; 1724*1f6eb021SLiane Praza 1725*1f6eb021SLiane Praza assert(fbufsz != 0 && nbufsz != 0 && tbufsz != 0); 1726*1f6eb021SLiane Praza 1727*1f6eb021SLiane Praza scf_tmpl_pg_reset(pg_tmpl); 1728*1f6eb021SLiane Praza 1729*1f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) 1730*1f6eb021SLiane Praza return (-1); 1731*1f6eb021SLiane Praza 1732*1f6eb021SLiane Praza if ((inst = scf_instance_create(h)) == NULL || 1733*1f6eb021SLiane Praza (svc = scf_service_create(h)) == NULL || 1734*1f6eb021SLiane Praza (snaplvl = scf_snaplevel_create(h)) == NULL) { 1735*1f6eb021SLiane Praza scf_instance_destroy(inst); 1736*1f6eb021SLiane Praza scf_service_destroy(svc); 1737*1f6eb021SLiane Praza return (-1); 1738*1f6eb021SLiane Praza } 1739*1f6eb021SLiane Praza 1740*1f6eb021SLiane Praza if ((fmribuf = malloc(fbufsz)) == NULL || 1741*1f6eb021SLiane Praza (pg_name = malloc(nbufsz)) == NULL || 1742*1f6eb021SLiane Praza (pg_type = malloc(tbufsz)) == NULL || 1743*1f6eb021SLiane Praza (p = calloc(1, sizeof (pg_tmpl_walk_t))) == NULL) { 1744*1f6eb021SLiane Praza free(fmribuf); 1745*1f6eb021SLiane Praza free(pg_name); 1746*1f6eb021SLiane Praza free(pg_type); 1747*1f6eb021SLiane Praza scf_instance_destroy(inst); 1748*1f6eb021SLiane Praza scf_service_destroy(svc); 1749*1f6eb021SLiane Praza scf_snaplevel_destroy(snaplvl); 1750*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1751*1f6eb021SLiane Praza return (-1); 1752*1f6eb021SLiane Praza } 1753*1f6eb021SLiane Praza 1754*1f6eb021SLiane Praza if (scf_pg_get_name(pg, pg_name, nbufsz) < 0) { 1755*1f6eb021SLiane Praza ret = -1; 1756*1f6eb021SLiane Praza goto fail; 1757*1f6eb021SLiane Praza } 1758*1f6eb021SLiane Praza 1759*1f6eb021SLiane Praza if (scf_pg_get_type(pg, pg_type, tbufsz) < 0) { 1760*1f6eb021SLiane Praza ret = -1; 1761*1f6eb021SLiane Praza goto fail; 1762*1f6eb021SLiane Praza } 1763*1f6eb021SLiane Praza p->pw_pgname = pg_name; 1764*1f6eb021SLiane Praza p->pw_pgtype = pg_type; 1765*1f6eb021SLiane Praza 1766*1f6eb021SLiane Praza ret = scf_pg_get_parent_snaplevel(pg, snaplvl); 1767*1f6eb021SLiane Praza if (ret == -1) { 1768*1f6eb021SLiane Praza switch (scf_error()) { 1769*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1770*1f6eb021SLiane Praza /* Parent type doesn't match. Keep looking. */ 1771*1f6eb021SLiane Praza break; 1772*1f6eb021SLiane Praza 1773*1f6eb021SLiane Praza case SCF_ERROR_DELETED: 1774*1f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 1775*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1776*1f6eb021SLiane Praza /* Pass these back to the caller. */ 1777*1f6eb021SLiane Praza goto fail; 1778*1f6eb021SLiane Praza 1779*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1780*1f6eb021SLiane Praza default: 1781*1f6eb021SLiane Praza assert(0); 1782*1f6eb021SLiane Praza abort(); 1783*1f6eb021SLiane Praza } 1784*1f6eb021SLiane Praza 1785*1f6eb021SLiane Praza /* 1786*1f6eb021SLiane Praza * No snapshot. We'll use 'editing' by default since 1787*1f6eb021SLiane Praza * snap and snapbuf are NULL. 1788*1f6eb021SLiane Praza */ 1789*1f6eb021SLiane Praza p->pw_snapname = NULL; 1790*1f6eb021SLiane Praza 1791*1f6eb021SLiane Praza } else { 1792*1f6eb021SLiane Praza if ((snap = scf_snapshot_create(h)) == NULL) { 1793*1f6eb021SLiane Praza ret = -1; 1794*1f6eb021SLiane Praza goto fail; 1795*1f6eb021SLiane Praza } 1796*1f6eb021SLiane Praza 1797*1f6eb021SLiane Praza ret = scf_snaplevel_get_parent(snaplvl, snap); 1798*1f6eb021SLiane Praza if (ret == -1) { 1799*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1800*1f6eb021SLiane Praza ret = -1; 1801*1f6eb021SLiane Praza goto fail; 1802*1f6eb021SLiane Praza } else { 1803*1f6eb021SLiane Praza assert(0); 1804*1f6eb021SLiane Praza abort(); 1805*1f6eb021SLiane Praza } 1806*1f6eb021SLiane Praza } 1807*1f6eb021SLiane Praza 1808*1f6eb021SLiane Praza /* Grab snapshot name while we're here. */ 1809*1f6eb021SLiane Praza if ((snapbuf = malloc(nbufsz)) == NULL) { 1810*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1811*1f6eb021SLiane Praza ret = -1; 1812*1f6eb021SLiane Praza goto fail; 1813*1f6eb021SLiane Praza } 1814*1f6eb021SLiane Praza if (scf_snapshot_get_name(snap, snapbuf, nbufsz) < 0) { 1815*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1816*1f6eb021SLiane Praza ret = -1; 1817*1f6eb021SLiane Praza goto fail; 1818*1f6eb021SLiane Praza } else { 1819*1f6eb021SLiane Praza assert(0); 1820*1f6eb021SLiane Praza abort(); 1821*1f6eb021SLiane Praza } 1822*1f6eb021SLiane Praza } 1823*1f6eb021SLiane Praza p->pw_snapname = snapbuf; 1824*1f6eb021SLiane Praza 1825*1f6eb021SLiane Praza ret = scf_snapshot_get_parent(snap, inst); 1826*1f6eb021SLiane Praza if (ret == -1) { 1827*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1828*1f6eb021SLiane Praza ret = -1; 1829*1f6eb021SLiane Praza goto fail; 1830*1f6eb021SLiane Praza } else { 1831*1f6eb021SLiane Praza assert(0); 1832*1f6eb021SLiane Praza abort(); 1833*1f6eb021SLiane Praza } 1834*1f6eb021SLiane Praza } 1835*1f6eb021SLiane Praza 1836*1f6eb021SLiane Praza _walk_template_instances(NULL, inst, snap, 1837*1f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, p, flags); 1838*1f6eb021SLiane Praza } 1839*1f6eb021SLiane Praza 1840*1f6eb021SLiane Praza /* No snapshot parent. Go looking for instance parent. */ 1841*1f6eb021SLiane Praza if (snapbuf == NULL) { 1842*1f6eb021SLiane Praza /* First look for instance parent. */ 1843*1f6eb021SLiane Praza ret = scf_pg_get_parent_instance(pg, inst); 1844*1f6eb021SLiane Praza if (ret == 0) { 1845*1f6eb021SLiane Praza _walk_template_instances(NULL, inst, snap, 1846*1f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, 1847*1f6eb021SLiane Praza p, flags); 1848*1f6eb021SLiane Praza /* OK, check for service parent */ 1849*1f6eb021SLiane Praza } else if (ret == -1 && 1850*1f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 1851*1f6eb021SLiane Praza ret = scf_pg_get_parent_service(pg, svc); 1852*1f6eb021SLiane Praza if (ret == 0) { 1853*1f6eb021SLiane Praza _walk_template_instances(svc, NULL, snap, 1854*1f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, 1855*1f6eb021SLiane Praza p, flags); 1856*1f6eb021SLiane Praza } else { 1857*1f6eb021SLiane Praza switch (scf_error()) { 1858*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1859*1f6eb021SLiane Praza (void) scf_set_error( 1860*1f6eb021SLiane Praza SCF_ERROR_NOT_FOUND); 1861*1f6eb021SLiane Praza /*FALLTHROUGH*/ 1862*1f6eb021SLiane Praza 1863*1f6eb021SLiane Praza case SCF_ERROR_CONNECTION_BROKEN: 1864*1f6eb021SLiane Praza case SCF_ERROR_DELETED: 1865*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1866*1f6eb021SLiane Praza case SCF_ERROR_NOT_BOUND: 1867*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1868*1f6eb021SLiane Praza ret = -1; 1869*1f6eb021SLiane Praza goto fail; 1870*1f6eb021SLiane Praza 1871*1f6eb021SLiane Praza default: 1872*1f6eb021SLiane Praza assert(0); 1873*1f6eb021SLiane Praza abort(); 1874*1f6eb021SLiane Praza } 1875*1f6eb021SLiane Praza } 1876*1f6eb021SLiane Praza } else { 1877*1f6eb021SLiane Praza ret = -1; 1878*1f6eb021SLiane Praza goto fail; 1879*1f6eb021SLiane Praza } 1880*1f6eb021SLiane Praza } 1881*1f6eb021SLiane Praza 1882*1f6eb021SLiane Praza if (p->pw_pg != NULL) { 1883*1f6eb021SLiane Praza pg_tmpl->pt_h = h; 1884*1f6eb021SLiane Praza pg_tmpl->pt_pg = p->pw_pg; 1885*1f6eb021SLiane Praza pg_tmpl->pt_inst = p->pw_inst; 1886*1f6eb021SLiane Praza pg_tmpl->pt_snap = p->pw_snap; 1887*1f6eb021SLiane Praza pg_tmpl->pt_svc = p->pw_svc; 1888*1f6eb021SLiane Praza pg_tmpl->pt_populated = 1; 1889*1f6eb021SLiane Praza free(p->pw_tmpl_pgname); 1890*1f6eb021SLiane Praza ret = 0; 1891*1f6eb021SLiane Praza goto done; 1892*1f6eb021SLiane Praza } 1893*1f6eb021SLiane Praza 1894*1f6eb021SLiane Praza ret = -1; 1895*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 1896*1f6eb021SLiane Praza 1897*1f6eb021SLiane Praza fail: 1898*1f6eb021SLiane Praza scf_instance_destroy(inst); 1899*1f6eb021SLiane Praza scf_service_destroy(svc); 1900*1f6eb021SLiane Praza scf_snapshot_destroy(snap); 1901*1f6eb021SLiane Praza done: 1902*1f6eb021SLiane Praza free(snapbuf); 1903*1f6eb021SLiane Praza free(fmribuf); 1904*1f6eb021SLiane Praza free(pg_name); 1905*1f6eb021SLiane Praza free(pg_type); 1906*1f6eb021SLiane Praza free(p); 1907*1f6eb021SLiane Praza scf_snaplevel_destroy(snaplvl); 1908*1f6eb021SLiane Praza return (ret); 1909*1f6eb021SLiane Praza } 1910*1f6eb021SLiane Praza 1911*1f6eb021SLiane Praza /* 1912*1f6eb021SLiane Praza * int scf_tmpl_get_by_pg_name() 1913*1f6eb021SLiane Praza * 1914*1f6eb021SLiane Praza * Get a template by a combination of the name and type. Either name 1915*1f6eb021SLiane Praza * or type can be null, which indicates a wildcard. flags may be 1916*1f6eb021SLiane Praza * SCF_PG_TMPL_FLAG_CURRENT (use current properties rather than 1917*1f6eb021SLiane Praza * the defined or running snapshot), and SCF_PG_TMPL_FLAG_EXACT (match 1918*1f6eb021SLiane Praza * only templates defined by the FMRI in question, not by its restarter 1919*1f6eb021SLiane Praza * or globally). Returns 0 on success and -1 on error, and sets 1920*1f6eb021SLiane Praza * scf_error() to: 1921*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 1922*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 1923*1f6eb021SLiane Praza * The connection to the repository was lost. 1924*1f6eb021SLiane Praza * SCF_ERROR_DELETED 1925*1f6eb021SLiane Praza * The instance has been deleted. 1926*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 1927*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 1928*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 1929*1f6eb021SLiane Praza * FMRI isn't valid, pg_name is too long to look for a template, or 1930*1f6eb021SLiane Praza * snapshot specified isn't a valid name 1931*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 1932*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 1933*1f6eb021SLiane Praza * The server does not have adequate resources to complete the request. 1934*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 1935*1f6eb021SLiane Praza * The handle is not currently bound. 1936*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 1937*1f6eb021SLiane Praza * Object matching FMRI doesn't exist in the repository, or snapshot 1938*1f6eb021SLiane Praza * doesn't exist. 1939*1f6eb021SLiane Praza */ 1940*1f6eb021SLiane Praza int 1941*1f6eb021SLiane Praza scf_tmpl_get_by_pg_name(const char *fmri, const char *snapshot, 1942*1f6eb021SLiane Praza const char *pg_name, const char *pg_type, scf_pg_tmpl_t *pg_tmpl, int flags) 1943*1f6eb021SLiane Praza { 1944*1f6eb021SLiane Praza scf_instance_t *inst = NULL; 1945*1f6eb021SLiane Praza scf_service_t *svc = NULL; 1946*1f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 1947*1f6eb021SLiane Praza pg_tmpl_walk_t *p; 1948*1f6eb021SLiane Praza scf_handle_t *h; 1949*1f6eb021SLiane Praza int ret; 1950*1f6eb021SLiane Praza 1951*1f6eb021SLiane Praza assert(pg_tmpl != NULL); 1952*1f6eb021SLiane Praza h = pg_tmpl->pt_h; 1953*1f6eb021SLiane Praza assert(h != NULL); 1954*1f6eb021SLiane Praza 1955*1f6eb021SLiane Praza scf_tmpl_pg_reset(pg_tmpl); 1956*1f6eb021SLiane Praza 1957*1f6eb021SLiane Praza if ((inst = scf_instance_create(h)) == NULL || 1958*1f6eb021SLiane Praza (svc = scf_service_create(h)) == NULL) { 1959*1f6eb021SLiane Praza scf_instance_destroy(inst); 1960*1f6eb021SLiane Praza return (-1); 1961*1f6eb021SLiane Praza } 1962*1f6eb021SLiane Praza 1963*1f6eb021SLiane Praza p = calloc(1, sizeof (pg_tmpl_walk_t)); 1964*1f6eb021SLiane Praza if (p == NULL) { 1965*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1966*1f6eb021SLiane Praza goto fail_zalloc; 1967*1f6eb021SLiane Praza } 1968*1f6eb021SLiane Praza 1969*1f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, 1970*1f6eb021SLiane Praza NULL, SCF_DECODE_FMRI_EXACT); 1971*1f6eb021SLiane Praza if (ret == 0) { 1972*1f6eb021SLiane Praza scf_service_destroy(svc); 1973*1f6eb021SLiane Praza svc = NULL; 1974*1f6eb021SLiane Praza } else if (ret != 0 && 1975*1f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 1976*1f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, svc, 1977*1f6eb021SLiane Praza NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT); 1978*1f6eb021SLiane Praza if (ret == 0) { 1979*1f6eb021SLiane Praza scf_instance_destroy(inst); 1980*1f6eb021SLiane Praza inst = NULL; 1981*1f6eb021SLiane Praza } 1982*1f6eb021SLiane Praza } 1983*1f6eb021SLiane Praza if (ret != 0) { 1984*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 1985*1f6eb021SLiane Praza goto fail; 1986*1f6eb021SLiane Praza } else switch (scf_error()) { 1987*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 1988*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1989*1f6eb021SLiane Praza goto fail; 1990*1f6eb021SLiane Praza 1991*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 1992*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 1993*1f6eb021SLiane Praza goto fail; 1994*1f6eb021SLiane Praza 1995*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 1996*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 1997*1f6eb021SLiane Praza default: 1998*1f6eb021SLiane Praza assert(0); 1999*1f6eb021SLiane Praza abort(); 2000*1f6eb021SLiane Praza } 2001*1f6eb021SLiane Praza } 2002*1f6eb021SLiane Praza 2003*1f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 2004*1f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 2005*1f6eb021SLiane Praza 2006*1f6eb021SLiane Praza if (inst != NULL) { 2007*1f6eb021SLiane Praza if (snapshot == NULL || strcmp(snapshot, "running") == 0 || 2008*1f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_CURRENT) == 2009*1f6eb021SLiane Praza SCF_PG_TMPL_FLAG_CURRENT) { 2010*1f6eb021SLiane Praza if (_get_snapshot(inst, NULL, &snap) == -1) 2011*1f6eb021SLiane Praza goto fail; 2012*1f6eb021SLiane Praza } else { 2013*1f6eb021SLiane Praza if (_get_snapshot(inst, snapshot, &snap) == -1) { 2014*1f6eb021SLiane Praza goto fail; 2015*1f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 2016*1f6eb021SLiane Praza goto fail; 2017*1f6eb021SLiane Praza } 2018*1f6eb021SLiane Praza } 2019*1f6eb021SLiane Praza } else { 2020*1f6eb021SLiane Praza /* If we have a service fmri, snapshot is ignored. */ 2021*1f6eb021SLiane Praza scf_snapshot_destroy(snap); 2022*1f6eb021SLiane Praza snap = NULL; 2023*1f6eb021SLiane Praza } 2024*1f6eb021SLiane Praza 2025*1f6eb021SLiane Praza p->pw_snapname = snapshot; 2026*1f6eb021SLiane Praza p->pw_pgname = pg_name; 2027*1f6eb021SLiane Praza p->pw_pgtype = pg_type; 2028*1f6eb021SLiane Praza 2029*1f6eb021SLiane Praza /* 2030*1f6eb021SLiane Praza * For each of instance, restarter, global 2031*1f6eb021SLiane Praza * - check for a tm_pg_pattern_nt_<name> matching type 2032*1f6eb021SLiane Praza * - check for a tm_pg_pattern_t_<type> matching type 2033*1f6eb021SLiane Praza * - check for any tm_pg_pattern_ 2034*1f6eb021SLiane Praza * Currently plan to return the most specific match only. 2035*1f6eb021SLiane Praza */ 2036*1f6eb021SLiane Praza _walk_template_instances(svc, inst, snap, 2037*1f6eb021SLiane Praza (walk_template_inst_func_t *)find_pg_match, p, flags); 2038*1f6eb021SLiane Praza 2039*1f6eb021SLiane Praza if (p->pw_pg != NULL) { 2040*1f6eb021SLiane Praza pg_tmpl->pt_h = h; 2041*1f6eb021SLiane Praza pg_tmpl->pt_pg = p->pw_pg; 2042*1f6eb021SLiane Praza pg_tmpl->pt_inst = p->pw_inst; 2043*1f6eb021SLiane Praza pg_tmpl->pt_snap = p->pw_snap; 2044*1f6eb021SLiane Praza pg_tmpl->pt_svc = p->pw_svc; 2045*1f6eb021SLiane Praza pg_tmpl->pt_populated = 1; 2046*1f6eb021SLiane Praza free(p->pw_tmpl_pgname); 2047*1f6eb021SLiane Praza free(p); 2048*1f6eb021SLiane Praza return (0); 2049*1f6eb021SLiane Praza } 2050*1f6eb021SLiane Praza 2051*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 2052*1f6eb021SLiane Praza fail: 2053*1f6eb021SLiane Praza free(p); 2054*1f6eb021SLiane Praza fail_zalloc: 2055*1f6eb021SLiane Praza scf_instance_destroy(inst); 2056*1f6eb021SLiane Praza scf_service_destroy(svc); 2057*1f6eb021SLiane Praza scf_snapshot_destroy(snap); 2058*1f6eb021SLiane Praza return (-1); 2059*1f6eb021SLiane Praza } 2060*1f6eb021SLiane Praza 2061*1f6eb021SLiane Praza /* 2062*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _CONNECTION_BROKEN, 2063*1f6eb021SLiane Praza * _DELETED, _NO_RESOURCES, or _NOT_BOUND. 2064*1f6eb021SLiane Praza */ 2065*1f6eb021SLiane Praza static scf_iter_t * 2066*1f6eb021SLiane Praza _get_svc_or_inst_iter(scf_handle_t *h, scf_pg_tmpl_t *t) 2067*1f6eb021SLiane Praza { 2068*1f6eb021SLiane Praza scf_iter_t *iter; 2069*1f6eb021SLiane Praza int ret; 2070*1f6eb021SLiane Praza 2071*1f6eb021SLiane Praza assert(t->pt_svc != NULL || t->pt_inst != NULL); 2072*1f6eb021SLiane Praza assert(t->pt_svc == NULL || t->pt_inst == NULL); 2073*1f6eb021SLiane Praza 2074*1f6eb021SLiane Praza if ((iter = scf_iter_create(h)) == NULL) { 2075*1f6eb021SLiane Praza return (NULL); 2076*1f6eb021SLiane Praza } 2077*1f6eb021SLiane Praza 2078*1f6eb021SLiane Praza /* Iterate on property groups of type template_pg_pattern */ 2079*1f6eb021SLiane Praza 2080*1f6eb021SLiane Praza if (t->pt_inst != NULL) 2081*1f6eb021SLiane Praza ret = scf_iter_instance_pgs_typed_composed(iter, 2082*1f6eb021SLiane Praza t->pt_inst, t->pt_snap, 2083*1f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN); 2084*1f6eb021SLiane Praza if (t->pt_svc != NULL) 2085*1f6eb021SLiane Praza ret = scf_iter_service_pgs_typed(iter, t->pt_svc, 2086*1f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN); 2087*1f6eb021SLiane Praza 2088*1f6eb021SLiane Praza if (ret != 0) { 2089*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2090*1f6eb021SLiane Praza scf_iter_destroy(iter); 2091*1f6eb021SLiane Praza return (NULL); 2092*1f6eb021SLiane Praza } else { 2093*1f6eb021SLiane Praza assert(0); 2094*1f6eb021SLiane Praza abort(); 2095*1f6eb021SLiane Praza } 2096*1f6eb021SLiane Praza } 2097*1f6eb021SLiane Praza 2098*1f6eb021SLiane Praza return (iter); 2099*1f6eb021SLiane Praza } 2100*1f6eb021SLiane Praza 2101*1f6eb021SLiane Praza /* 2102*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 2103*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2104*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2105*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2106*1f6eb021SLiane Praza * SCF_HANDLE_DESTROYED 2107*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2108*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2109*1f6eb021SLiane Praza * Handle argument is NULL, or snaphot is not a valid snapshot name. 2110*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2111*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2112*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2113*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 2114*1f6eb021SLiane Praza */ 2115*1f6eb021SLiane Praza static scf_iter_t * 2116*1f6eb021SLiane Praza _get_next_iterator(scf_handle_t *h, scf_pg_tmpl_t *t, const char *snapshot, 2117*1f6eb021SLiane Praza int exact) 2118*1f6eb021SLiane Praza { 2119*1f6eb021SLiane Praza scf_iter_t *iter = NULL; 2120*1f6eb021SLiane Praza ssize_t limit; 2121*1f6eb021SLiane Praza 2122*1f6eb021SLiane Praza limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 2123*1f6eb021SLiane Praza assert(limit != 0); 2124*1f6eb021SLiane Praza 2125*1f6eb021SLiane Praza /* 2126*1f6eb021SLiane Praza * Check what level we last iterated on: none, service, 2127*1f6eb021SLiane Praza * restarter, or global. Make sure that if one in the middle 2128*1f6eb021SLiane Praza * doesn't exist, we move on to the next entity. 2129*1f6eb021SLiane Praza */ 2130*1f6eb021SLiane Praza do { 2131*1f6eb021SLiane Praza switch (t->pt_iter_last) { 2132*1f6eb021SLiane Praza case SCF__TMPL_ITER_NONE: 2133*1f6eb021SLiane Praza t->pt_iter_last = SCF__TMPL_ITER_INST; 2134*1f6eb021SLiane Praza t->pt_inst = t->pt_orig_inst; 2135*1f6eb021SLiane Praza t->pt_svc = t->pt_orig_svc; 2136*1f6eb021SLiane Praza break; 2137*1f6eb021SLiane Praza 2138*1f6eb021SLiane Praza case SCF__TMPL_ITER_INST: 2139*1f6eb021SLiane Praza /* 2140*1f6eb021SLiane Praza * Don't go any further than the specified instance 2141*1f6eb021SLiane Praza * if exact was set. 2142*1f6eb021SLiane Praza */ 2143*1f6eb021SLiane Praza if (exact == 1) { 2144*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 2145*1f6eb021SLiane Praza goto fail; 2146*1f6eb021SLiane Praza } 2147*1f6eb021SLiane Praza t->pt_iter_last = SCF__TMPL_ITER_RESTARTER; 2148*1f6eb021SLiane Praza t->pt_inst = _get_restarter_inst(h, t->pt_orig_svc, 2149*1f6eb021SLiane Praza t->pt_orig_inst, t->pt_snap); 2150*1f6eb021SLiane Praza t->pt_svc = NULL; 2151*1f6eb021SLiane Praza break; 2152*1f6eb021SLiane Praza 2153*1f6eb021SLiane Praza case SCF__TMPL_ITER_RESTARTER: 2154*1f6eb021SLiane Praza t->pt_iter_last = SCF__TMPL_ITER_GLOBAL; 2155*1f6eb021SLiane Praza t->pt_inst = _get_global_inst(h); 2156*1f6eb021SLiane Praza t->pt_svc = NULL; 2157*1f6eb021SLiane Praza break; 2158*1f6eb021SLiane Praza 2159*1f6eb021SLiane Praza case SCF__TMPL_ITER_GLOBAL: 2160*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 2161*1f6eb021SLiane Praza return (NULL); 2162*1f6eb021SLiane Praza 2163*1f6eb021SLiane Praza default: 2164*1f6eb021SLiane Praza assert(0); 2165*1f6eb021SLiane Praza abort(); 2166*1f6eb021SLiane Praza } 2167*1f6eb021SLiane Praza } while (t->pt_inst == NULL && t->pt_svc == NULL); 2168*1f6eb021SLiane Praza 2169*1f6eb021SLiane Praza /* Set pt_snap to the snapshot for this instance */ 2170*1f6eb021SLiane Praza if (t->pt_inst != NULL) { 2171*1f6eb021SLiane Praza scf_snapshot_destroy(t->pt_snap); 2172*1f6eb021SLiane Praza if (_get_snapshot(t->pt_inst, snapshot, 2173*1f6eb021SLiane Praza &t->pt_snap) == -1) 2174*1f6eb021SLiane Praza goto fail; 2175*1f6eb021SLiane Praza } 2176*1f6eb021SLiane Praza 2177*1f6eb021SLiane Praza 2178*1f6eb021SLiane Praza iter = _get_svc_or_inst_iter(h, t); 2179*1f6eb021SLiane Praza fail: 2180*1f6eb021SLiane Praza return (iter); 2181*1f6eb021SLiane Praza } 2182*1f6eb021SLiane Praza 2183*1f6eb021SLiane Praza /* 2184*1f6eb021SLiane Praza * scf_pg_tmpl_t *scf_tmpl_pg_create(scf_handle_t *) 2185*1f6eb021SLiane Praza * 2186*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT 2187*1f6eb021SLiane Praza * or _NO_MEMORY. 2188*1f6eb021SLiane Praza */ 2189*1f6eb021SLiane Praza scf_pg_tmpl_t * 2190*1f6eb021SLiane Praza scf_tmpl_pg_create(scf_handle_t *handle) 2191*1f6eb021SLiane Praza { 2192*1f6eb021SLiane Praza scf_pg_tmpl_t *pg_tmpl = NULL; 2193*1f6eb021SLiane Praza 2194*1f6eb021SLiane Praza if (handle == NULL) { 2195*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2196*1f6eb021SLiane Praza return (NULL); 2197*1f6eb021SLiane Praza } 2198*1f6eb021SLiane Praza pg_tmpl = calloc(1, sizeof (scf_pg_tmpl_t)); 2199*1f6eb021SLiane Praza if (pg_tmpl == NULL) 2200*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2201*1f6eb021SLiane Praza else 2202*1f6eb021SLiane Praza pg_tmpl->pt_h = handle; 2203*1f6eb021SLiane Praza 2204*1f6eb021SLiane Praza return (pg_tmpl); 2205*1f6eb021SLiane Praza } 2206*1f6eb021SLiane Praza 2207*1f6eb021SLiane Praza /* 2208*1f6eb021SLiane Praza * Retrieves name or type of a template pg. 2209*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 2210*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2211*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2212*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2213*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2214*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2215*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2216*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2217*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2218*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 2219*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 2220*1f6eb021SLiane Praza * pname property is not SCF_TYPE_ASTRING or has more than one value. 2221*1f6eb021SLiane Praza */ 2222*1f6eb021SLiane Praza static ssize_t 2223*1f6eb021SLiane Praza _scf_tmpl_prop_value(scf_propertygroup_t *pg, const char *pname, char **out) 2224*1f6eb021SLiane Praza { 2225*1f6eb021SLiane Praza assert(strcmp(pname, SCF_PROPERTY_TM_NAME) == 0 || 2226*1f6eb021SLiane Praza strcmp(pname, SCF_PROPERTY_TM_TYPE) == 0); 2227*1f6eb021SLiane Praza 2228*1f6eb021SLiane Praza *out = _scf_read_single_astring_from_pg(pg, pname); 2229*1f6eb021SLiane Praza 2230*1f6eb021SLiane Praza if (*out != NULL && *out[0] == '\0') { 2231*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 2232*1f6eb021SLiane Praza free(*out); 2233*1f6eb021SLiane Praza *out = strdup(SCF_TMPL_WILDCARD); 2234*1f6eb021SLiane Praza if (*out == NULL) 2235*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2236*1f6eb021SLiane Praza } 2237*1f6eb021SLiane Praza if (*out == NULL) { 2238*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2239*1f6eb021SLiane Praza return (-1); 2240*1f6eb021SLiane Praza } else switch (scf_error()) { 2241*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 2242*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 2243*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 2244*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 2245*1f6eb021SLiane Praza return (-1); 2246*1f6eb021SLiane Praza 2247*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 2248*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 2249*1f6eb021SLiane Praza default: 2250*1f6eb021SLiane Praza assert(0); 2251*1f6eb021SLiane Praza abort(); 2252*1f6eb021SLiane Praza } 2253*1f6eb021SLiane Praza } 2254*1f6eb021SLiane Praza 2255*1f6eb021SLiane Praza return (strlen(*out)); 2256*1f6eb021SLiane Praza } 2257*1f6eb021SLiane Praza 2258*1f6eb021SLiane Praza /* 2259*1f6eb021SLiane Praza * int scf_tmpl_iter_pgs() 2260*1f6eb021SLiane Praza * 2261*1f6eb021SLiane Praza * Iterates through the property group templates for the fmri given. 2262*1f6eb021SLiane Praza * When t is uninitialized or reset, sets t to the first property group 2263*1f6eb021SLiane Praza * template in fmri. On subsequent calls, sets t to the next property group 2264*1f6eb021SLiane Praza * template in frmi. 2265*1f6eb021SLiane Praza * Returns 1 on success, 0 when no property group templates are left to 2266*1f6eb021SLiane Praza * iterate, -1 on error. 2267*1f6eb021SLiane Praza * The flags argument may include SCF_PG_TMPL_FLAG_REQUIRED, 2268*1f6eb021SLiane Praza * SCF_PG_TMPL_FLAG_CURRENT, and/or SCF_PG_TMPL_FLAG_EXACT. 2269*1f6eb021SLiane Praza * 2270*1f6eb021SLiane Praza * Returns -1 on error and sets scf_error() to: 2271*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2272*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2273*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2274*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2275*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2276*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2277*1f6eb021SLiane Praza * The handle argument is NULL, fmri is invalid, or snapshot is invalid. 2278*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2279*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2280*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2281*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 2282*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 2283*1f6eb021SLiane Praza */ 2284*1f6eb021SLiane Praza int 2285*1f6eb021SLiane Praza scf_tmpl_iter_pgs(scf_pg_tmpl_t *t, const char *fmri, const char *snapshot, 2286*1f6eb021SLiane Praza const char *type, int flags) 2287*1f6eb021SLiane Praza { 2288*1f6eb021SLiane Praza scf_handle_t *h; 2289*1f6eb021SLiane Praza scf_service_t *svc = NULL; 2290*1f6eb021SLiane Praza scf_instance_t *inst = NULL; 2291*1f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 2292*1f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 2293*1f6eb021SLiane Praza scf_pg_tmpl_t *pg_tmpl = NULL; 2294*1f6eb021SLiane Praza int err; 2295*1f6eb021SLiane Praza int found = 0; 2296*1f6eb021SLiane Praza char *tmpl_type; 2297*1f6eb021SLiane Praza uint8_t required; 2298*1f6eb021SLiane Praza int ret; 2299*1f6eb021SLiane Praza 2300*1f6eb021SLiane Praza if (t == NULL) { 2301*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2302*1f6eb021SLiane Praza return (-1); 2303*1f6eb021SLiane Praza } 2304*1f6eb021SLiane Praza 2305*1f6eb021SLiane Praza h = t->pt_h; 2306*1f6eb021SLiane Praza 2307*1f6eb021SLiane Praza if (t->pt_populated == 0) { 2308*1f6eb021SLiane Praza if ((svc = scf_service_create(h)) == NULL || 2309*1f6eb021SLiane Praza (inst = scf_instance_create(h)) == NULL || 2310*1f6eb021SLiane Praza (pg = scf_pg_create(h)) == NULL) { 2311*1f6eb021SLiane Praza goto fail_non_populated; 2312*1f6eb021SLiane Praza } 2313*1f6eb021SLiane Praza 2314*1f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, 2315*1f6eb021SLiane Praza NULL, SCF_DECODE_FMRI_EXACT); 2316*1f6eb021SLiane Praza if (ret == 0) { 2317*1f6eb021SLiane Praza scf_service_destroy(svc); 2318*1f6eb021SLiane Praza svc = NULL; 2319*1f6eb021SLiane Praza } else if (ret != 0 && 2320*1f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 2321*1f6eb021SLiane Praza ret = scf_handle_decode_fmri(h, fmri, NULL, svc, 2322*1f6eb021SLiane Praza NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT); 2323*1f6eb021SLiane Praza if (ret == 0) { 2324*1f6eb021SLiane Praza scf_instance_destroy(inst); 2325*1f6eb021SLiane Praza inst = NULL; 2326*1f6eb021SLiane Praza } 2327*1f6eb021SLiane Praza } 2328*1f6eb021SLiane Praza 2329*1f6eb021SLiane Praza if (ret != 0) { 2330*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2331*1f6eb021SLiane Praza goto fail_non_populated; 2332*1f6eb021SLiane Praza } else switch (scf_error()) { 2333*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 2334*1f6eb021SLiane Praza (void) scf_set_error( 2335*1f6eb021SLiane Praza SCF_ERROR_INVALID_ARGUMENT); 2336*1f6eb021SLiane Praza goto fail_non_populated; 2337*1f6eb021SLiane Praza 2338*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 2339*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 2340*1f6eb021SLiane Praza goto fail_non_populated; 2341*1f6eb021SLiane Praza 2342*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 2343*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 2344*1f6eb021SLiane Praza default: 2345*1f6eb021SLiane Praza assert(0); 2346*1f6eb021SLiane Praza abort(); 2347*1f6eb021SLiane Praza } 2348*1f6eb021SLiane Praza } 2349*1f6eb021SLiane Praza 2350*1f6eb021SLiane Praza assert(svc == NULL || inst == NULL); 2351*1f6eb021SLiane Praza assert(svc != NULL || inst != NULL); 2352*1f6eb021SLiane Praza 2353*1f6eb021SLiane Praza if (inst != NULL) { 2354*1f6eb021SLiane Praza if (snapshot == NULL || 2355*1f6eb021SLiane Praza strcmp(snapshot, "running") == 0 || 2356*1f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_CURRENT) == 2357*1f6eb021SLiane Praza SCF_PG_TMPL_FLAG_CURRENT) { 2358*1f6eb021SLiane Praza if (_get_snapshot(inst, NULL, &snap) == -1) 2359*1f6eb021SLiane Praza goto fail_non_populated; 2360*1f6eb021SLiane Praza } else { 2361*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 2362*1f6eb021SLiane Praza if (_get_snapshot(inst, snapshot, 2363*1f6eb021SLiane Praza &snap) == -1) { 2364*1f6eb021SLiane Praza goto fail_non_populated; 2365*1f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 2366*1f6eb021SLiane Praza goto fail_non_populated; 2367*1f6eb021SLiane Praza } 2368*1f6eb021SLiane Praza } 2369*1f6eb021SLiane Praza } else { 2370*1f6eb021SLiane Praza scf_snapshot_destroy(snap); 2371*1f6eb021SLiane Praza snap = NULL; 2372*1f6eb021SLiane Praza } 2373*1f6eb021SLiane Praza 2374*1f6eb021SLiane Praza pg_tmpl = t; 2375*1f6eb021SLiane Praza pg_tmpl->pt_orig_inst = inst; 2376*1f6eb021SLiane Praza pg_tmpl->pt_orig_svc = svc; 2377*1f6eb021SLiane Praza pg_tmpl->pt_snap = snap; 2378*1f6eb021SLiane Praza pg_tmpl->pt_is_iter = 1; 2379*1f6eb021SLiane Praza pg_tmpl->pt_iter_last = SCF__TMPL_ITER_NONE; 2380*1f6eb021SLiane Praza pg_tmpl->pt_pg = pg; 2381*1f6eb021SLiane Praza pg_tmpl->pt_populated = 1; 2382*1f6eb021SLiane Praza } else { 2383*1f6eb021SLiane Praza if (t->pt_is_iter != 1) { 2384*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2385*1f6eb021SLiane Praza return (-1); 2386*1f6eb021SLiane Praza } 2387*1f6eb021SLiane Praza pg_tmpl = t; 2388*1f6eb021SLiane Praza assert(pg_tmpl->pt_pg != NULL); 2389*1f6eb021SLiane Praza } 2390*1f6eb021SLiane Praza 2391*1f6eb021SLiane Praza if (pg_tmpl->pt_iter == NULL) { 2392*1f6eb021SLiane Praza pg_tmpl->pt_iter = _get_next_iterator(h, pg_tmpl, snapshot, 2393*1f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0); 2394*1f6eb021SLiane Praza if (pg_tmpl->pt_iter == NULL) { 2395*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 2396*1f6eb021SLiane Praza return (0); 2397*1f6eb021SLiane Praza else 2398*1f6eb021SLiane Praza return (-1); 2399*1f6eb021SLiane Praza } 2400*1f6eb021SLiane Praza } 2401*1f6eb021SLiane Praza 2402*1f6eb021SLiane Praza while (found == 0) { 2403*1f6eb021SLiane Praza while ((err = scf_iter_next_pg(pg_tmpl->pt_iter, 2404*1f6eb021SLiane Praza pg_tmpl->pt_pg)) != 1) { 2405*1f6eb021SLiane Praza if (err == -1) { 2406*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2407*1f6eb021SLiane Praza return (-1); 2408*1f6eb021SLiane Praza } else switch (scf_error()) { 2409*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 2410*1f6eb021SLiane Praza return (-1); 2411*1f6eb021SLiane Praza 2412*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 2413*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 2414*1f6eb021SLiane Praza default: 2415*1f6eb021SLiane Praza assert(0); 2416*1f6eb021SLiane Praza abort(); 2417*1f6eb021SLiane Praza } 2418*1f6eb021SLiane Praza } else if (err == 0) { 2419*1f6eb021SLiane Praza /* This iteration is done. Get the next one */ 2420*1f6eb021SLiane Praza scf_iter_destroy(pg_tmpl->pt_iter); 2421*1f6eb021SLiane Praza pg_tmpl->pt_iter = _get_next_iterator(h, 2422*1f6eb021SLiane Praza pg_tmpl, snapshot, 2423*1f6eb021SLiane Praza (flags & SCF_PG_TMPL_FLAG_EXACT) ? 1 : 0); 2424*1f6eb021SLiane Praza if (pg_tmpl->pt_iter == NULL) { 2425*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 2426*1f6eb021SLiane Praza return (0); 2427*1f6eb021SLiane Praza else 2428*1f6eb021SLiane Praza return (-1); 2429*1f6eb021SLiane Praza } 2430*1f6eb021SLiane Praza continue; 2431*1f6eb021SLiane Praza } else { 2432*1f6eb021SLiane Praza assert(0); 2433*1f6eb021SLiane Praza abort(); 2434*1f6eb021SLiane Praza } 2435*1f6eb021SLiane Praza } 2436*1f6eb021SLiane Praza 2437*1f6eb021SLiane Praza /* 2438*1f6eb021SLiane Praza * Discard pgs which don't exist at the right scoping. This 2439*1f6eb021SLiane Praza * check also makes sure that if we're looking at, for 2440*1f6eb021SLiane Praza * example, svc:/system/svc/restarter:default, that we 2441*1f6eb021SLiane Praza * don't hand back the same property groups twice. 2442*1f6eb021SLiane Praza */ 2443*1f6eb021SLiane Praza switch (t->pt_iter_last) { 2444*1f6eb021SLiane Praza case SCF__TMPL_ITER_INST: 2445*1f6eb021SLiane Praza ret = check_target_match(pg_tmpl->pt_pg, 2446*1f6eb021SLiane Praza SCF_TM_TARGET_THIS); 2447*1f6eb021SLiane Praza break; 2448*1f6eb021SLiane Praza case SCF__TMPL_ITER_RESTARTER: 2449*1f6eb021SLiane Praza ret = check_target_match(pg_tmpl->pt_pg, 2450*1f6eb021SLiane Praza SCF_TM_TARGET_DELEGATE); 2451*1f6eb021SLiane Praza break; 2452*1f6eb021SLiane Praza case SCF__TMPL_ITER_GLOBAL: 2453*1f6eb021SLiane Praza ret = check_target_match(pg_tmpl->pt_pg, 2454*1f6eb021SLiane Praza SCF_TM_TARGET_ALL); 2455*1f6eb021SLiane Praza break; 2456*1f6eb021SLiane Praza case SCF__TMPL_ITER_NONE: 2457*1f6eb021SLiane Praza default: 2458*1f6eb021SLiane Praza assert(0); 2459*1f6eb021SLiane Praza abort(); 2460*1f6eb021SLiane Praza } 2461*1f6eb021SLiane Praza 2462*1f6eb021SLiane Praza if (ret != 0) 2463*1f6eb021SLiane Praza continue; 2464*1f6eb021SLiane Praza 2465*1f6eb021SLiane Praza /* 2466*1f6eb021SLiane Praza * If walking only required property groups, check if 2467*1f6eb021SLiane Praza * the retrieved group is required. 2468*1f6eb021SLiane Praza */ 2469*1f6eb021SLiane Praza if (flags & SCF_PG_TMPL_FLAG_REQUIRED) { 2470*1f6eb021SLiane Praza if (scf_tmpl_pg_required(pg_tmpl, &required) == 0) { 2471*1f6eb021SLiane Praza if (required == 0) 2472*1f6eb021SLiane Praza continue; 2473*1f6eb021SLiane Praza } else { 2474*1f6eb021SLiane Praza return (-1); 2475*1f6eb021SLiane Praza } 2476*1f6eb021SLiane Praza } 2477*1f6eb021SLiane Praza 2478*1f6eb021SLiane Praza /* 2479*1f6eb021SLiane Praza * If type != NULL, check if type property matches. If no 2480*1f6eb021SLiane Praza * type property exists, consider it a match. 2481*1f6eb021SLiane Praza */ 2482*1f6eb021SLiane Praza if (type != NULL) { 2483*1f6eb021SLiane Praza if (scf_tmpl_pg_type(pg_tmpl, &tmpl_type) != -1) { 2484*1f6eb021SLiane Praza if (strcmp(tmpl_type, SCF_TMPL_WILDCARD) 2485*1f6eb021SLiane Praza == 0 || strcmp(type, tmpl_type) == 0) { 2486*1f6eb021SLiane Praza free(tmpl_type); 2487*1f6eb021SLiane Praza break; 2488*1f6eb021SLiane Praza } 2489*1f6eb021SLiane Praza free(tmpl_type); 2490*1f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND || 2491*1f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED || 2492*1f6eb021SLiane Praza scf_error() == SCF_ERROR_TYPE_MISMATCH) { 2493*1f6eb021SLiane Praza break; 2494*1f6eb021SLiane Praza } else { 2495*1f6eb021SLiane Praza return (-1); 2496*1f6eb021SLiane Praza } 2497*1f6eb021SLiane Praza } else { 2498*1f6eb021SLiane Praza break; 2499*1f6eb021SLiane Praza } 2500*1f6eb021SLiane Praza } 2501*1f6eb021SLiane Praza 2502*1f6eb021SLiane Praza return (1); 2503*1f6eb021SLiane Praza 2504*1f6eb021SLiane Praza fail_non_populated: 2505*1f6eb021SLiane Praza scf_service_destroy(svc); 2506*1f6eb021SLiane Praza scf_instance_destroy(inst); 2507*1f6eb021SLiane Praza scf_pg_destroy(pg); 2508*1f6eb021SLiane Praza scf_snapshot_destroy(snap); 2509*1f6eb021SLiane Praza return (-1); 2510*1f6eb021SLiane Praza } 2511*1f6eb021SLiane Praza 2512*1f6eb021SLiane Praza void 2513*1f6eb021SLiane Praza scf_tmpl_pg_destroy(scf_pg_tmpl_t *t) 2514*1f6eb021SLiane Praza { 2515*1f6eb021SLiane Praza if (t == NULL) 2516*1f6eb021SLiane Praza return; 2517*1f6eb021SLiane Praza 2518*1f6eb021SLiane Praza scf_pg_destroy(t->pt_pg); 2519*1f6eb021SLiane Praza scf_instance_destroy(t->pt_inst); 2520*1f6eb021SLiane Praza if (t->pt_inst != t->pt_orig_inst) 2521*1f6eb021SLiane Praza scf_instance_destroy(t->pt_orig_inst); 2522*1f6eb021SLiane Praza scf_snapshot_destroy(t->pt_snap); 2523*1f6eb021SLiane Praza scf_service_destroy(t->pt_orig_svc); 2524*1f6eb021SLiane Praza if (t->pt_svc != t->pt_orig_svc) 2525*1f6eb021SLiane Praza scf_service_destroy(t->pt_svc); 2526*1f6eb021SLiane Praza scf_iter_destroy(t->pt_iter); 2527*1f6eb021SLiane Praza free(t); 2528*1f6eb021SLiane Praza } 2529*1f6eb021SLiane Praza 2530*1f6eb021SLiane Praza void 2531*1f6eb021SLiane Praza scf_tmpl_pg_reset(scf_pg_tmpl_t *t) 2532*1f6eb021SLiane Praza { 2533*1f6eb021SLiane Praza scf_pg_destroy(t->pt_pg); 2534*1f6eb021SLiane Praza t->pt_pg = NULL; 2535*1f6eb021SLiane Praza 2536*1f6eb021SLiane Praza scf_instance_destroy(t->pt_inst); 2537*1f6eb021SLiane Praza if (t->pt_inst != t->pt_orig_inst) 2538*1f6eb021SLiane Praza scf_instance_destroy(t->pt_orig_inst); 2539*1f6eb021SLiane Praza t->pt_inst = NULL; 2540*1f6eb021SLiane Praza t->pt_orig_inst = NULL; 2541*1f6eb021SLiane Praza 2542*1f6eb021SLiane Praza scf_snapshot_destroy(t->pt_snap); 2543*1f6eb021SLiane Praza t->pt_snap = NULL; 2544*1f6eb021SLiane Praza 2545*1f6eb021SLiane Praza scf_service_destroy(t->pt_orig_svc); 2546*1f6eb021SLiane Praza if (t->pt_svc != t->pt_orig_svc) 2547*1f6eb021SLiane Praza scf_service_destroy(t->pt_svc); 2548*1f6eb021SLiane Praza t->pt_orig_svc = NULL; 2549*1f6eb021SLiane Praza t->pt_svc = NULL; 2550*1f6eb021SLiane Praza 2551*1f6eb021SLiane Praza scf_iter_destroy(t->pt_iter); 2552*1f6eb021SLiane Praza t->pt_iter = NULL; 2553*1f6eb021SLiane Praza 2554*1f6eb021SLiane Praza t->pt_populated = 0; 2555*1f6eb021SLiane Praza t->pt_is_iter = 0; 2556*1f6eb021SLiane Praza t->pt_iter_last = 0; 2557*1f6eb021SLiane Praza 2558*1f6eb021SLiane Praza /* Do not reset t->pt_h. */ 2559*1f6eb021SLiane Praza } 2560*1f6eb021SLiane Praza 2561*1f6eb021SLiane Praza /* 2562*1f6eb021SLiane Praza * int scf_tmpl_get_by_prop() 2563*1f6eb021SLiane Praza * 2564*1f6eb021SLiane Praza * Get the property template given a property group template and property 2565*1f6eb021SLiane Praza * name. No flags are currently defined for this function. 2566*1f6eb021SLiane Praza * 2567*1f6eb021SLiane Praza * Returns NULL on failure, and sets scf_error(): 2568*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2569*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2570*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2571*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2572*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2573*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2574*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2575*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2576*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2577*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 2578*1f6eb021SLiane Praza * Template object matching property doesn't exist in the repository. 2579*1f6eb021SLiane Praza * SCF_ERROR_TYPE_MISMATCH 2580*1f6eb021SLiane Praza * Matching template object is the wrong type in the repository. 2581*1f6eb021SLiane Praza */ 2582*1f6eb021SLiane Praza int 2583*1f6eb021SLiane Praza scf_tmpl_get_by_prop(scf_pg_tmpl_t *t, const char *prop, 2584*1f6eb021SLiane Praza scf_prop_tmpl_t *prop_tmpl, int flags) 2585*1f6eb021SLiane Praza { 2586*1f6eb021SLiane Praza char *tmpl_prop_name; 2587*1f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 2588*1f6eb021SLiane Praza char *pg_type; 2589*1f6eb021SLiane Praza int found = 0; 2590*1f6eb021SLiane Praza 2591*1f6eb021SLiane Praza if (flags != 0) { 2592*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2593*1f6eb021SLiane Praza return (-1); 2594*1f6eb021SLiane Praza } 2595*1f6eb021SLiane Praza 2596*1f6eb021SLiane Praza scf_tmpl_prop_reset(prop_tmpl); 2597*1f6eb021SLiane Praza if ((pg = scf_pg_create(scf_pg_handle(t->pt_pg))) == NULL) 2598*1f6eb021SLiane Praza return (-1); 2599*1f6eb021SLiane Praza 2600*1f6eb021SLiane Praza tmpl_prop_name = _tmpl_prop_name(prop, t); 2601*1f6eb021SLiane Praza if (tmpl_prop_name == NULL) { 2602*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 2603*1f6eb021SLiane Praza return (-1); 2604*1f6eb021SLiane Praza } 2605*1f6eb021SLiane Praza 2606*1f6eb021SLiane Praza if (_get_pg(t->pt_svc, t->pt_inst, t->pt_snap, 2607*1f6eb021SLiane Praza tmpl_prop_name, pg) != 0) { 2608*1f6eb021SLiane Praza if (!ismember(scf_error(), errors_server)) { 2609*1f6eb021SLiane Praza switch (scf_error()) { 2610*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 2611*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 2612*1f6eb021SLiane Praza break; 2613*1f6eb021SLiane Praza 2614*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 2615*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 2616*1f6eb021SLiane Praza default: 2617*1f6eb021SLiane Praza assert(0); 2618*1f6eb021SLiane Praza abort(); 2619*1f6eb021SLiane Praza } 2620*1f6eb021SLiane Praza } 2621*1f6eb021SLiane Praza } else { 2622*1f6eb021SLiane Praza /* 2623*1f6eb021SLiane Praza * We've only found a template property group if the type 2624*1f6eb021SLiane Praza * is correct. 2625*1f6eb021SLiane Praza */ 2626*1f6eb021SLiane Praza if ((pg_type = _scf_get_pg_type(pg)) != NULL && 2627*1f6eb021SLiane Praza strcmp(pg_type, SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0) 2628*1f6eb021SLiane Praza found++; 2629*1f6eb021SLiane Praza else 2630*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TYPE_MISMATCH); 2631*1f6eb021SLiane Praza 2632*1f6eb021SLiane Praza 2633*1f6eb021SLiane Praza free(pg_type); 2634*1f6eb021SLiane Praza } 2635*1f6eb021SLiane Praza 2636*1f6eb021SLiane Praza if (found == 0) { 2637*1f6eb021SLiane Praza scf_pg_destroy(pg); 2638*1f6eb021SLiane Praza free(tmpl_prop_name); 2639*1f6eb021SLiane Praza return (-1); 2640*1f6eb021SLiane Praza } 2641*1f6eb021SLiane Praza 2642*1f6eb021SLiane Praza prop_tmpl->prt_h = scf_pg_handle(t->pt_pg); 2643*1f6eb021SLiane Praza prop_tmpl->prt_t = t; 2644*1f6eb021SLiane Praza prop_tmpl->prt_pg = pg; 2645*1f6eb021SLiane Praza prop_tmpl->prt_pg_name = tmpl_prop_name; 2646*1f6eb021SLiane Praza prop_tmpl->prt_populated = 1; 2647*1f6eb021SLiane Praza 2648*1f6eb021SLiane Praza return (0); 2649*1f6eb021SLiane Praza } 2650*1f6eb021SLiane Praza 2651*1f6eb021SLiane Praza /* 2652*1f6eb021SLiane Praza * scf_prop_tmpl_t *scf_tmpl_prop_create(scf_handle_t *); 2653*1f6eb021SLiane Praza * 2654*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT, or 2655*1f6eb021SLiane Praza * _NO_MEMORY. 2656*1f6eb021SLiane Praza */ 2657*1f6eb021SLiane Praza scf_prop_tmpl_t * 2658*1f6eb021SLiane Praza scf_tmpl_prop_create(scf_handle_t *handle) 2659*1f6eb021SLiane Praza { 2660*1f6eb021SLiane Praza scf_prop_tmpl_t *pt; 2661*1f6eb021SLiane Praza 2662*1f6eb021SLiane Praza if (handle == NULL) { 2663*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2664*1f6eb021SLiane Praza return (NULL); 2665*1f6eb021SLiane Praza } 2666*1f6eb021SLiane Praza pt = calloc(1, sizeof (scf_prop_tmpl_t)); 2667*1f6eb021SLiane Praza if (pt == NULL) 2668*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2669*1f6eb021SLiane Praza else 2670*1f6eb021SLiane Praza pt->prt_h = handle; 2671*1f6eb021SLiane Praza 2672*1f6eb021SLiane Praza return (pt); 2673*1f6eb021SLiane Praza } 2674*1f6eb021SLiane Praza 2675*1f6eb021SLiane Praza /* 2676*1f6eb021SLiane Praza * int scf_tmpl_iter_props() 2677*1f6eb021SLiane Praza * 2678*1f6eb021SLiane Praza * Iterates over all property templates defined in the specified property 2679*1f6eb021SLiane Praza * group template. The iterator state is stored on the property template 2680*1f6eb021SLiane Praza * data structure, and the data structure should be allocated with 2681*1f6eb021SLiane Praza * scf_tmpl_prop_create(). To continue the iteration, the previously 2682*1f6eb021SLiane Praza * returned structure should be passed in as an argument to this function. 2683*1f6eb021SLiane Praza * flags can include SCF_PROP_TMPL_FLAG_REQUIRED. The function returns 2684*1f6eb021SLiane Praza * 1 when a result was found, and 0 when the iteration is complete. 2685*1f6eb021SLiane Praza * 2686*1f6eb021SLiane Praza * Returns -1 on failure, and sets scf_error(): 2687*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2688*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2689*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2690*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2691*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2692*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2693*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2694*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2695*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2696*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 2697*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 2698*1f6eb021SLiane Praza * Template data is invalid. One of the property templates in this 2699*1f6eb021SLiane Praza * pg_tmpl is malformed. 2700*1f6eb021SLiane Praza */ 2701*1f6eb021SLiane Praza int 2702*1f6eb021SLiane Praza scf_tmpl_iter_props(scf_pg_tmpl_t *t, scf_prop_tmpl_t *pt, int flags) 2703*1f6eb021SLiane Praza { 2704*1f6eb021SLiane Praza scf_prop_tmpl_t *prop_tmpl; 2705*1f6eb021SLiane Praza char *pg_pat; 2706*1f6eb021SLiane Praza char *pg_name = NULL; 2707*1f6eb021SLiane Praza int err; 2708*1f6eb021SLiane Praza int ret; 2709*1f6eb021SLiane Praza ssize_t size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 2710*1f6eb021SLiane Praza uint8_t required; 2711*1f6eb021SLiane Praza scf_handle_t *h; 2712*1f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 2713*1f6eb021SLiane Praza scf_iter_t *iter = NULL; 2714*1f6eb021SLiane Praza 2715*1f6eb021SLiane Praza assert(size != 0); 2716*1f6eb021SLiane Praza if (t == NULL || pt == NULL) { 2717*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2718*1f6eb021SLiane Praza return (-1); 2719*1f6eb021SLiane Praza } 2720*1f6eb021SLiane Praza 2721*1f6eb021SLiane Praza assert(t->pt_inst == NULL || t->pt_svc == NULL); 2722*1f6eb021SLiane Praza assert(t->pt_inst != NULL || t->pt_svc != NULL); 2723*1f6eb021SLiane Praza 2724*1f6eb021SLiane Praza if ((pg_name = malloc(size)) == NULL) { 2725*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2726*1f6eb021SLiane Praza return (-1); 2727*1f6eb021SLiane Praza } 2728*1f6eb021SLiane Praza 2729*1f6eb021SLiane Praza if (pt->prt_populated == 0) { 2730*1f6eb021SLiane Praza if ((h = scf_pg_handle(t->pt_pg)) == NULL) 2731*1f6eb021SLiane Praza goto fail_non_populated; 2732*1f6eb021SLiane Praza 2733*1f6eb021SLiane Praza if ((pg = scf_pg_create(h)) == NULL || 2734*1f6eb021SLiane Praza (iter = scf_iter_create(h)) == NULL) 2735*1f6eb021SLiane Praza goto fail_non_populated; 2736*1f6eb021SLiane Praza 2737*1f6eb021SLiane Praza if (t->pt_inst != NULL) 2738*1f6eb021SLiane Praza err = scf_iter_instance_pgs_typed_composed(iter, 2739*1f6eb021SLiane Praza t->pt_inst, t->pt_snap, 2740*1f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PROP_PATTERN); 2741*1f6eb021SLiane Praza else if (t->pt_svc != NULL) 2742*1f6eb021SLiane Praza err = scf_iter_service_pgs_typed(iter, t->pt_svc, 2743*1f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PROP_PATTERN); 2744*1f6eb021SLiane Praza 2745*1f6eb021SLiane Praza if (err != 0) { 2746*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2747*1f6eb021SLiane Praza goto fail_non_populated; 2748*1f6eb021SLiane Praza } else switch (scf_error()) { 2749*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 2750*1f6eb021SLiane Praza goto fail_non_populated; 2751*1f6eb021SLiane Praza 2752*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 2753*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 2754*1f6eb021SLiane Praza default: 2755*1f6eb021SLiane Praza assert(0); 2756*1f6eb021SLiane Praza abort(); 2757*1f6eb021SLiane Praza } 2758*1f6eb021SLiane Praza 2759*1f6eb021SLiane Praza } 2760*1f6eb021SLiane Praza prop_tmpl = pt; 2761*1f6eb021SLiane Praza prop_tmpl->prt_t = t; 2762*1f6eb021SLiane Praza prop_tmpl->prt_populated = 1; 2763*1f6eb021SLiane Praza prop_tmpl->prt_pg = pg; 2764*1f6eb021SLiane Praza prop_tmpl->prt_iter = iter; 2765*1f6eb021SLiane Praza } else { 2766*1f6eb021SLiane Praza prop_tmpl = pt; 2767*1f6eb021SLiane Praza } 2768*1f6eb021SLiane Praza 2769*1f6eb021SLiane Praza while ((err = scf_iter_next_pg(prop_tmpl->prt_iter, 2770*1f6eb021SLiane Praza prop_tmpl->prt_pg)) > 0) { 2771*1f6eb021SLiane Praza /* 2772*1f6eb021SLiane Praza * Check if the name matches the appropriate property 2773*1f6eb021SLiane Praza * group template name. 2774*1f6eb021SLiane Praza */ 2775*1f6eb021SLiane Praza pg_pat = _scf_read_single_astring_from_pg(prop_tmpl->prt_pg, 2776*1f6eb021SLiane Praza SCF_PROPERTY_TM_PG_PATTERN); 2777*1f6eb021SLiane Praza if (pg_pat == NULL) { 2778*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2779*1f6eb021SLiane Praza uu_free(pg_name); 2780*1f6eb021SLiane Praza return (-1); 2781*1f6eb021SLiane Praza } else switch (scf_error()) { 2782*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 2783*1f6eb021SLiane Praza continue; 2784*1f6eb021SLiane Praza 2785*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 2786*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 2787*1f6eb021SLiane Praza (void) scf_set_error( 2788*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 2789*1f6eb021SLiane Praza free(pg_name); 2790*1f6eb021SLiane Praza return (-1); 2791*1f6eb021SLiane Praza 2792*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 2793*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 2794*1f6eb021SLiane Praza default: 2795*1f6eb021SLiane Praza assert(0); 2796*1f6eb021SLiane Praza abort(); 2797*1f6eb021SLiane Praza } 2798*1f6eb021SLiane Praza } 2799*1f6eb021SLiane Praza if ((ret = scf_pg_get_name(t->pt_pg, pg_name, size)) <= 0) { 2800*1f6eb021SLiane Praza free(pg_pat); 2801*1f6eb021SLiane Praza if (ret == 0) 2802*1f6eb021SLiane Praza continue; 2803*1f6eb021SLiane Praza 2804*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2805*1f6eb021SLiane Praza free(pg_name); 2806*1f6eb021SLiane Praza return (-1); 2807*1f6eb021SLiane Praza } else { 2808*1f6eb021SLiane Praza assert(0); 2809*1f6eb021SLiane Praza abort(); 2810*1f6eb021SLiane Praza } 2811*1f6eb021SLiane Praza } 2812*1f6eb021SLiane Praza if (strcmp(pg_pat, pg_name) != 0) { 2813*1f6eb021SLiane Praza free(pg_pat); 2814*1f6eb021SLiane Praza continue; 2815*1f6eb021SLiane Praza } 2816*1f6eb021SLiane Praza free(pg_pat); 2817*1f6eb021SLiane Praza 2818*1f6eb021SLiane Praza /* 2819*1f6eb021SLiane Praza * If walking only required properties, check if 2820*1f6eb021SLiane Praza * the retrieved property is required. 2821*1f6eb021SLiane Praza */ 2822*1f6eb021SLiane Praza if (flags & SCF_PROP_TMPL_FLAG_REQUIRED) { 2823*1f6eb021SLiane Praza if (scf_tmpl_prop_required(prop_tmpl, &required) == 0) { 2824*1f6eb021SLiane Praza if (required == 0) 2825*1f6eb021SLiane Praza continue; 2826*1f6eb021SLiane Praza } else { 2827*1f6eb021SLiane Praza free(pg_name); 2828*1f6eb021SLiane Praza return (-1); 2829*1f6eb021SLiane Praza } 2830*1f6eb021SLiane Praza } 2831*1f6eb021SLiane Praza free(pg_name); 2832*1f6eb021SLiane Praza return (0); 2833*1f6eb021SLiane Praza } 2834*1f6eb021SLiane Praza 2835*1f6eb021SLiane Praza if (err == -1) { 2836*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 2837*1f6eb021SLiane Praza free(pg_name); 2838*1f6eb021SLiane Praza return (-1); 2839*1f6eb021SLiane Praza } else { 2840*1f6eb021SLiane Praza assert(0); 2841*1f6eb021SLiane Praza abort(); 2842*1f6eb021SLiane Praza } 2843*1f6eb021SLiane Praza } else if (err == 0) { 2844*1f6eb021SLiane Praza scf_iter_destroy(prop_tmpl->prt_iter); 2845*1f6eb021SLiane Praza prop_tmpl->prt_iter = NULL; 2846*1f6eb021SLiane Praza prop_tmpl->prt_populated = 0; 2847*1f6eb021SLiane Praza } 2848*1f6eb021SLiane Praza free(pg_name); 2849*1f6eb021SLiane Praza 2850*1f6eb021SLiane Praza return (1); 2851*1f6eb021SLiane Praza 2852*1f6eb021SLiane Praza fail_non_populated: 2853*1f6eb021SLiane Praza free(pg_name); 2854*1f6eb021SLiane Praza scf_pg_destroy(pg); 2855*1f6eb021SLiane Praza scf_iter_destroy(iter); 2856*1f6eb021SLiane Praza return (-1); 2857*1f6eb021SLiane Praza } 2858*1f6eb021SLiane Praza 2859*1f6eb021SLiane Praza void 2860*1f6eb021SLiane Praza scf_tmpl_prop_destroy(scf_prop_tmpl_t *t) 2861*1f6eb021SLiane Praza { 2862*1f6eb021SLiane Praza if (t == NULL) 2863*1f6eb021SLiane Praza return; 2864*1f6eb021SLiane Praza 2865*1f6eb021SLiane Praza scf_pg_destroy(t->prt_pg); 2866*1f6eb021SLiane Praza free(t->prt_pg_name); 2867*1f6eb021SLiane Praza free(t->prt_iter); 2868*1f6eb021SLiane Praza free(t); 2869*1f6eb021SLiane Praza } 2870*1f6eb021SLiane Praza 2871*1f6eb021SLiane Praza void 2872*1f6eb021SLiane Praza scf_tmpl_prop_reset(scf_prop_tmpl_t *t) 2873*1f6eb021SLiane Praza { 2874*1f6eb021SLiane Praza scf_pg_destroy(t->prt_pg); 2875*1f6eb021SLiane Praza t->prt_pg = NULL; 2876*1f6eb021SLiane Praza 2877*1f6eb021SLiane Praza free(t->prt_pg_name); 2878*1f6eb021SLiane Praza t->prt_pg_name = NULL; 2879*1f6eb021SLiane Praza 2880*1f6eb021SLiane Praza free(t->prt_iter); 2881*1f6eb021SLiane Praza t->prt_iter = NULL; 2882*1f6eb021SLiane Praza 2883*1f6eb021SLiane Praza t->prt_populated = 0; 2884*1f6eb021SLiane Praza t->prt_h = NULL; 2885*1f6eb021SLiane Praza t->prt_t = NULL; 2886*1f6eb021SLiane Praza } 2887*1f6eb021SLiane Praza 2888*1f6eb021SLiane Praza /* 2889*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 2890*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2891*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2892*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2893*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2894*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2895*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2896*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2897*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2898*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 2899*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 2900*1f6eb021SLiane Praza * The name of the template property group (the pname property) has 2901*1f6eb021SLiane Praza * an improper repository format and is not type astring or has 2902*1f6eb021SLiane Praza * more than one value. 2903*1f6eb021SLiane Praza */ 2904*1f6eb021SLiane Praza ssize_t 2905*1f6eb021SLiane Praza scf_tmpl_pg_name(const scf_pg_tmpl_t *t, char **out) 2906*1f6eb021SLiane Praza { 2907*1f6eb021SLiane Praza return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_NAME, out)); 2908*1f6eb021SLiane Praza } 2909*1f6eb021SLiane Praza 2910*1f6eb021SLiane Praza /* 2911*1f6eb021SLiane Praza * returns an allocated string that must be freed 2912*1f6eb021SLiane Praza * 2913*1f6eb021SLiane Praza * Returns NULL on failure, sets scf_error() to: 2914*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2915*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2916*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2917*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2918*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2919*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2920*1f6eb021SLiane Praza * name not a valid property name 2921*1f6eb021SLiane Praza * name and locale are too long to make a property name 2922*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2923*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2924*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2925*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 2926*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 2927*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 2928*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 2929*1f6eb021SLiane Praza */ 2930*1f6eb021SLiane Praza static char * 2931*1f6eb021SLiane Praza _read_localized_astring_from_pg(scf_propertygroup_t *pg, const char *name, 2932*1f6eb021SLiane Praza const char *locale) 2933*1f6eb021SLiane Praza { 2934*1f6eb021SLiane Praza char *str; 2935*1f6eb021SLiane Praza char *lname_prop; 2936*1f6eb021SLiane Praza 2937*1f6eb021SLiane Praza str = _add_locale_to_name(name, locale); 2938*1f6eb021SLiane Praza if (str == NULL) 2939*1f6eb021SLiane Praza return (NULL); 2940*1f6eb021SLiane Praza lname_prop = _scf_read_single_astring_from_pg(pg, str); 2941*1f6eb021SLiane Praza if (lname_prop == NULL) { 2942*1f6eb021SLiane Praza free(str); 2943*1f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) 2944*1f6eb021SLiane Praza return (NULL); 2945*1f6eb021SLiane Praza str = _add_locale_to_name(name, "C"); 2946*1f6eb021SLiane Praza if (str == NULL) 2947*1f6eb021SLiane Praza return (NULL); 2948*1f6eb021SLiane Praza lname_prop = _scf_read_single_astring_from_pg(pg, str); 2949*1f6eb021SLiane Praza } 2950*1f6eb021SLiane Praza free(str); 2951*1f6eb021SLiane Praza if (lname_prop == NULL) { 2952*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_TYPE_MISMATCH || 2953*1f6eb021SLiane Praza scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) 2954*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 2955*1f6eb021SLiane Praza } 2956*1f6eb021SLiane Praza return (lname_prop); 2957*1f6eb021SLiane Praza } 2958*1f6eb021SLiane Praza 2959*1f6eb021SLiane Praza /* 2960*1f6eb021SLiane Praza * returns an allocated string that must be freed 2961*1f6eb021SLiane Praza * 2962*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 2963*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2964*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2965*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2966*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2967*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2968*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2969*1f6eb021SLiane Praza * locale is too long to make a valid property name 2970*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 2971*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 2972*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 2973*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 2974*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 2975*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 2976*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 2977*1f6eb021SLiane Praza */ 2978*1f6eb021SLiane Praza ssize_t 2979*1f6eb021SLiane Praza scf_tmpl_pg_common_name(const scf_pg_tmpl_t *t, const char *locale, char **out) 2980*1f6eb021SLiane Praza { 2981*1f6eb021SLiane Praza assert(out != NULL); 2982*1f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->pt_pg, 2983*1f6eb021SLiane Praza SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL) 2984*1f6eb021SLiane Praza return (-1); 2985*1f6eb021SLiane Praza 2986*1f6eb021SLiane Praza return (strlen(*out)); 2987*1f6eb021SLiane Praza } 2988*1f6eb021SLiane Praza 2989*1f6eb021SLiane Praza /* 2990*1f6eb021SLiane Praza * returns an allocated string that must be freed 2991*1f6eb021SLiane Praza * 2992*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 2993*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 2994*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 2995*1f6eb021SLiane Praza * SCF_ERROR_DELETED 2996*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 2997*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 2998*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 2999*1f6eb021SLiane Praza * locale is too long to make a valid property name 3000*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3001*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3002*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3003*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3004*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3005*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3006*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3007*1f6eb021SLiane Praza */ 3008*1f6eb021SLiane Praza ssize_t 3009*1f6eb021SLiane Praza scf_tmpl_pg_description(const scf_pg_tmpl_t *t, const char *locale, char **out) 3010*1f6eb021SLiane Praza { 3011*1f6eb021SLiane Praza assert(out != NULL); 3012*1f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->pt_pg, 3013*1f6eb021SLiane Praza SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL) 3014*1f6eb021SLiane Praza return (-1); 3015*1f6eb021SLiane Praza 3016*1f6eb021SLiane Praza return (strlen(*out)); 3017*1f6eb021SLiane Praza } 3018*1f6eb021SLiane Praza 3019*1f6eb021SLiane Praza /* 3020*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3021*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3022*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3023*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3024*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3025*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3026*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3027*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3028*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3029*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3030*1f6eb021SLiane Praza * 'type' property doesn't exist or exists and has no value. 3031*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3032*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3033*1f6eb021SLiane Praza * 'type' property is not SCF_TYPE_ASTRING or has more than one value. 3034*1f6eb021SLiane Praza */ 3035*1f6eb021SLiane Praza ssize_t 3036*1f6eb021SLiane Praza scf_tmpl_pg_type(const scf_pg_tmpl_t *t, char **out) 3037*1f6eb021SLiane Praza { 3038*1f6eb021SLiane Praza return (_scf_tmpl_prop_value(t->pt_pg, SCF_PROPERTY_TM_TYPE, out)); 3039*1f6eb021SLiane Praza } 3040*1f6eb021SLiane Praza 3041*1f6eb021SLiane Praza /* 3042*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 3043*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3044*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3045*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3046*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3047*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3048*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3049*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3050*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3051*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3052*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3053*1f6eb021SLiane Praza * required property is not SCF_TYPE_BOOLEAN or has more than one value. 3054*1f6eb021SLiane Praza */ 3055*1f6eb021SLiane Praza int 3056*1f6eb021SLiane Praza scf_tmpl_pg_required(const scf_pg_tmpl_t *t, uint8_t *out) 3057*1f6eb021SLiane Praza { 3058*1f6eb021SLiane Praza 3059*1f6eb021SLiane Praza if (_read_single_boolean_from_pg(t->pt_pg, SCF_PROPERTY_TM_REQUIRED, 3060*1f6eb021SLiane Praza out) == -1) { 3061*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3062*1f6eb021SLiane Praza return (-1); 3063*1f6eb021SLiane Praza } else switch (scf_error()) { 3064*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3065*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3066*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3067*1f6eb021SLiane Praza return (-1); 3068*1f6eb021SLiane Praza 3069*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3070*1f6eb021SLiane Praza *out = 0; 3071*1f6eb021SLiane Praza return (0); 3072*1f6eb021SLiane Praza 3073*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3074*1f6eb021SLiane Praza default: 3075*1f6eb021SLiane Praza assert(0); 3076*1f6eb021SLiane Praza abort(); 3077*1f6eb021SLiane Praza } 3078*1f6eb021SLiane Praza } 3079*1f6eb021SLiane Praza 3080*1f6eb021SLiane Praza return (0); 3081*1f6eb021SLiane Praza } 3082*1f6eb021SLiane Praza 3083*1f6eb021SLiane Praza /* 3084*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3085*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3086*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3087*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3088*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3089*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3090*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3091*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3092*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3093*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3094*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3095*1f6eb021SLiane Praza * target property is not SCF_TYPE_ASTRING or has more than one value. 3096*1f6eb021SLiane Praza */ 3097*1f6eb021SLiane Praza ssize_t 3098*1f6eb021SLiane Praza scf_tmpl_pg_target(const scf_pg_tmpl_t *t, char **out) 3099*1f6eb021SLiane Praza { 3100*1f6eb021SLiane Praza *out = _scf_read_single_astring_from_pg(t->pt_pg, 3101*1f6eb021SLiane Praza SCF_PROPERTY_TM_TARGET); 3102*1f6eb021SLiane Praza 3103*1f6eb021SLiane Praza if (*out == NULL) { 3104*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3105*1f6eb021SLiane Praza return (-1); 3106*1f6eb021SLiane Praza } else switch (scf_error()) { 3107*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3108*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3109*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3110*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3111*1f6eb021SLiane Praza return (-1); 3112*1f6eb021SLiane Praza 3113*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3114*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3115*1f6eb021SLiane Praza default: 3116*1f6eb021SLiane Praza assert(0); 3117*1f6eb021SLiane Praza abort(); 3118*1f6eb021SLiane Praza } 3119*1f6eb021SLiane Praza } 3120*1f6eb021SLiane Praza 3121*1f6eb021SLiane Praza return (strlen(*out)); 3122*1f6eb021SLiane Praza } 3123*1f6eb021SLiane Praza 3124*1f6eb021SLiane Praza /* 3125*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3126*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3127*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3128*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3129*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3130*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3131*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3132*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3133*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3134*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3135*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3136*1f6eb021SLiane Praza */ 3137*1f6eb021SLiane Praza ssize_t 3138*1f6eb021SLiane Praza scf_tmpl_prop_name(const scf_prop_tmpl_t *t, char **out) 3139*1f6eb021SLiane Praza { 3140*1f6eb021SLiane Praza *out = _scf_read_single_astring_from_pg(t->prt_pg, 3141*1f6eb021SLiane Praza SCF_PROPERTY_TM_NAME); 3142*1f6eb021SLiane Praza 3143*1f6eb021SLiane Praza if (*out != NULL && *out[0] == '\0') { 3144*1f6eb021SLiane Praza free(*out); 3145*1f6eb021SLiane Praza *out = NULL; 3146*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3147*1f6eb021SLiane Praza } 3148*1f6eb021SLiane Praza if (*out == NULL) { 3149*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3150*1f6eb021SLiane Praza return (-1); 3151*1f6eb021SLiane Praza } else switch (scf_error()) { 3152*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3153*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3154*1f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 3155*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3156*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3157*1f6eb021SLiane Praza return (-1); 3158*1f6eb021SLiane Praza 3159*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3160*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3161*1f6eb021SLiane Praza default: 3162*1f6eb021SLiane Praza assert(0); 3163*1f6eb021SLiane Praza abort(); 3164*1f6eb021SLiane Praza } 3165*1f6eb021SLiane Praza } 3166*1f6eb021SLiane Praza 3167*1f6eb021SLiane Praza return (strlen(*out)); 3168*1f6eb021SLiane Praza } 3169*1f6eb021SLiane Praza 3170*1f6eb021SLiane Praza /* 3171*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3172*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3173*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3174*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3175*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3176*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3177*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3178*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3179*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3180*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3181*1f6eb021SLiane Praza * 'type' property doesn't exist or exists and has no value. 3182*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3183*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3184*1f6eb021SLiane Praza * 'type' property is not SCF_TYPE_ASTRING, has more than one value, 3185*1f6eb021SLiane Praza * is SCF_TYPE_INVALID, or is the empty string. 3186*1f6eb021SLiane Praza */ 3187*1f6eb021SLiane Praza int 3188*1f6eb021SLiane Praza scf_tmpl_prop_type(const scf_prop_tmpl_t *t, scf_type_t *out) 3189*1f6eb021SLiane Praza { 3190*1f6eb021SLiane Praza char *type; 3191*1f6eb021SLiane Praza 3192*1f6eb021SLiane Praza type = _scf_read_single_astring_from_pg(t->prt_pg, 3193*1f6eb021SLiane Praza SCF_PROPERTY_TM_TYPE); 3194*1f6eb021SLiane Praza if (type != NULL && type[0] == '\0') { 3195*1f6eb021SLiane Praza free(type); 3196*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 3197*1f6eb021SLiane Praza return (-1); 3198*1f6eb021SLiane Praza } 3199*1f6eb021SLiane Praza if (type == NULL) { 3200*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3201*1f6eb021SLiane Praza return (-1); 3202*1f6eb021SLiane Praza } else switch (scf_error()) { 3203*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3204*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3205*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3206*1f6eb021SLiane Praza /*FALLTHROUGH*/ 3207*1f6eb021SLiane Praza 3208*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3209*1f6eb021SLiane Praza return (-1); 3210*1f6eb021SLiane Praza 3211*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3212*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3213*1f6eb021SLiane Praza default: 3214*1f6eb021SLiane Praza assert(0); 3215*1f6eb021SLiane Praza abort(); 3216*1f6eb021SLiane Praza } 3217*1f6eb021SLiane Praza } 3218*1f6eb021SLiane Praza 3219*1f6eb021SLiane Praza *out = scf_string_to_type(type); 3220*1f6eb021SLiane Praza free(type); 3221*1f6eb021SLiane Praza 3222*1f6eb021SLiane Praza if (*out == SCF_TYPE_INVALID) { 3223*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3224*1f6eb021SLiane Praza return (-1); 3225*1f6eb021SLiane Praza } 3226*1f6eb021SLiane Praza 3227*1f6eb021SLiane Praza return (0); 3228*1f6eb021SLiane Praza } 3229*1f6eb021SLiane Praza 3230*1f6eb021SLiane Praza /* 3231*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 3232*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3233*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3234*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3235*1f6eb021SLiane Praza * Property group which represents t was deleted. 3236*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3237*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3238*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3239*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3240*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3241*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3242*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3243*1f6eb021SLiane Praza * required property is not SCF_TYPE_ASTRING has more than one value. 3244*1f6eb021SLiane Praza */ 3245*1f6eb021SLiane Praza int 3246*1f6eb021SLiane Praza scf_tmpl_prop_required(const scf_prop_tmpl_t *t, uint8_t *out) 3247*1f6eb021SLiane Praza { 3248*1f6eb021SLiane Praza if (_read_single_boolean_from_pg(t->prt_pg, SCF_PROPERTY_TM_REQUIRED, 3249*1f6eb021SLiane Praza out) == -1) { 3250*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3251*1f6eb021SLiane Praza return (-1); 3252*1f6eb021SLiane Praza } else switch (scf_error()) { 3253*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3254*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3255*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3256*1f6eb021SLiane Praza return (-1); 3257*1f6eb021SLiane Praza 3258*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3259*1f6eb021SLiane Praza *out = 0; 3260*1f6eb021SLiane Praza return (0); 3261*1f6eb021SLiane Praza 3262*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3263*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3264*1f6eb021SLiane Praza default: 3265*1f6eb021SLiane Praza assert(0); 3266*1f6eb021SLiane Praza abort(); 3267*1f6eb021SLiane Praza } 3268*1f6eb021SLiane Praza } 3269*1f6eb021SLiane Praza 3270*1f6eb021SLiane Praza return (0); 3271*1f6eb021SLiane Praza } 3272*1f6eb021SLiane Praza 3273*1f6eb021SLiane Praza /* 3274*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3275*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3276*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3277*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3278*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3279*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3280*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3281*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3282*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3283*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3284*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3285*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 3286*1f6eb021SLiane Praza * locale is too long to make a property name 3287*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3288*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3289*1f6eb021SLiane Praza * common_name property is not SCF_TYPE_ASTRING has more than one value. 3290*1f6eb021SLiane Praza */ 3291*1f6eb021SLiane Praza ssize_t 3292*1f6eb021SLiane Praza scf_tmpl_prop_common_name(const scf_prop_tmpl_t *t, const char *locale, 3293*1f6eb021SLiane Praza char **out) 3294*1f6eb021SLiane Praza { 3295*1f6eb021SLiane Praza assert(out != NULL); 3296*1f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->prt_pg, 3297*1f6eb021SLiane Praza SCF_PROPERTY_TM_COMMON_NAME_PREFIX, locale)) == NULL) 3298*1f6eb021SLiane Praza return (-1); 3299*1f6eb021SLiane Praza 3300*1f6eb021SLiane Praza return (strlen(*out)); 3301*1f6eb021SLiane Praza } 3302*1f6eb021SLiane Praza 3303*1f6eb021SLiane Praza /* 3304*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3305*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3306*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3307*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3308*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3309*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3310*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3311*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3312*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3313*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3314*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3315*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 3316*1f6eb021SLiane Praza * locale is too long to make a property name 3317*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3318*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3319*1f6eb021SLiane Praza * description property is not SCF_TYPE_ASTRING has more than one value. 3320*1f6eb021SLiane Praza */ 3321*1f6eb021SLiane Praza ssize_t 3322*1f6eb021SLiane Praza scf_tmpl_prop_description(const scf_prop_tmpl_t *t, const char *locale, 3323*1f6eb021SLiane Praza char **out) 3324*1f6eb021SLiane Praza { 3325*1f6eb021SLiane Praza assert(out != NULL); 3326*1f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->prt_pg, 3327*1f6eb021SLiane Praza SCF_PROPERTY_TM_DESCRIPTION_PREFIX, locale)) == NULL) 3328*1f6eb021SLiane Praza return (-1); 3329*1f6eb021SLiane Praza 3330*1f6eb021SLiane Praza return (strlen(*out)); 3331*1f6eb021SLiane Praza } 3332*1f6eb021SLiane Praza 3333*1f6eb021SLiane Praza /* 3334*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3335*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3336*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3337*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3338*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3339*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3340*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3341*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3342*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3343*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3344*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3345*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 3346*1f6eb021SLiane Praza * locale is too long to make a property name 3347*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3348*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3349*1f6eb021SLiane Praza * units property is not SCF_TYPE_ASTRING has more than one value. 3350*1f6eb021SLiane Praza */ 3351*1f6eb021SLiane Praza ssize_t 3352*1f6eb021SLiane Praza scf_tmpl_prop_units(const scf_prop_tmpl_t *t, const char *locale, char **out) 3353*1f6eb021SLiane Praza { 3354*1f6eb021SLiane Praza assert(out != NULL); 3355*1f6eb021SLiane Praza if ((*out = _read_localized_astring_from_pg(t->prt_pg, 3356*1f6eb021SLiane Praza SCF_PROPERTY_TM_UNITS_PREFIX, locale)) == NULL) 3357*1f6eb021SLiane Praza return (-1); 3358*1f6eb021SLiane Praza 3359*1f6eb021SLiane Praza return (strlen(*out)); 3360*1f6eb021SLiane Praza } 3361*1f6eb021SLiane Praza 3362*1f6eb021SLiane Praza /* 3363*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3364*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3365*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3366*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3367*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3368*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3369*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3370*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3371*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3372*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3373*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3374*1f6eb021SLiane Praza * visibility property is not SCF_TYPE_ASTRING has more than one value. 3375*1f6eb021SLiane Praza */ 3376*1f6eb021SLiane Praza int 3377*1f6eb021SLiane Praza scf_tmpl_prop_visibility(const scf_prop_tmpl_t *t, uint8_t *out) 3378*1f6eb021SLiane Praza { 3379*1f6eb021SLiane Praza char *visibility; 3380*1f6eb021SLiane Praza 3381*1f6eb021SLiane Praza visibility = _scf_read_single_astring_from_pg(t->prt_pg, 3382*1f6eb021SLiane Praza SCF_PROPERTY_TM_VISIBILITY); 3383*1f6eb021SLiane Praza if (visibility == NULL) { 3384*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3385*1f6eb021SLiane Praza return (-1); 3386*1f6eb021SLiane Praza } else switch (scf_error()) { 3387*1f6eb021SLiane Praza /* prop doesn't exist we take the default value */ 3388*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3389*1f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_READWRITE; 3390*1f6eb021SLiane Praza return (0); 3391*1f6eb021SLiane Praza 3392*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3393*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3394*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3395*1f6eb021SLiane Praza return (-1); 3396*1f6eb021SLiane Praza 3397*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3398*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3399*1f6eb021SLiane Praza default: 3400*1f6eb021SLiane Praza assert(0); 3401*1f6eb021SLiane Praza abort(); 3402*1f6eb021SLiane Praza } 3403*1f6eb021SLiane Praza } else if (strcmp(visibility, SCF_TM_VISIBILITY_READWRITE) == 0) { 3404*1f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_READWRITE; 3405*1f6eb021SLiane Praza } else if (strcmp(visibility, SCF_TM_VISIBILITY_HIDDEN) == 0) { 3406*1f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_HIDDEN; 3407*1f6eb021SLiane Praza } else if (strcmp(visibility, SCF_TM_VISIBILITY_READONLY) == 0) { 3408*1f6eb021SLiane Praza *out = SCF_TMPL_VISIBILITY_READONLY; 3409*1f6eb021SLiane Praza } else { 3410*1f6eb021SLiane Praza free(visibility); 3411*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3412*1f6eb021SLiane Praza return (-1); 3413*1f6eb021SLiane Praza } 3414*1f6eb021SLiane Praza 3415*1f6eb021SLiane Praza free(visibility); 3416*1f6eb021SLiane Praza return (0); 3417*1f6eb021SLiane Praza } 3418*1f6eb021SLiane Praza 3419*1f6eb021SLiane Praza /* 3420*1f6eb021SLiane Praza * Return an allocated string containing the value that must be freed 3421*1f6eb021SLiane Praza * with free(). 3422*1f6eb021SLiane Praza * 3423*1f6eb021SLiane Praza * On error set scf_error() _NO_MEMORY, or _NOT_SET (val has not been set 3424*1f6eb021SLiane Praza * to a value). 3425*1f6eb021SLiane Praza */ 3426*1f6eb021SLiane Praza static char * 3427*1f6eb021SLiane Praza _scf_value_get_as_string(scf_value_t *val) 3428*1f6eb021SLiane Praza { 3429*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 3430*1f6eb021SLiane Praza char *buf = malloc(sz); 3431*1f6eb021SLiane Praza 3432*1f6eb021SLiane Praza if (buf == NULL) { 3433*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3434*1f6eb021SLiane Praza } else if (scf_value_get_as_string(val, buf, sz) == -1) { 3435*1f6eb021SLiane Praza free(buf); 3436*1f6eb021SLiane Praza buf = NULL; 3437*1f6eb021SLiane Praza } 3438*1f6eb021SLiane Praza 3439*1f6eb021SLiane Praza return (buf); 3440*1f6eb021SLiane Praza } 3441*1f6eb021SLiane Praza 3442*1f6eb021SLiane Praza /* 3443*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 3444*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3445*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3446*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3447*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3448*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3449*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3450*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3451*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3452*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3453*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3454*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3455*1f6eb021SLiane Praza */ 3456*1f6eb021SLiane Praza int 3457*1f6eb021SLiane Praza scf_tmpl_prop_cardinality(const scf_prop_tmpl_t *t, uint64_t *min, 3458*1f6eb021SLiane Praza uint64_t *max) 3459*1f6eb021SLiane Praza { 3460*1f6eb021SLiane Praza scf_value_t *val_min = NULL; 3461*1f6eb021SLiane Praza scf_value_t *val_max = NULL; 3462*1f6eb021SLiane Praza int ret = 0; 3463*1f6eb021SLiane Praza 3464*1f6eb021SLiane Praza if (_read_single_value_from_pg(t->prt_pg, 3465*1f6eb021SLiane Praza SCF_PROPERTY_TM_CARDINALITY_MIN, &val_min) == 0) { 3466*1f6eb021SLiane Praza if (scf_value_get_count(val_min, min) < 0) 3467*1f6eb021SLiane Praza goto error; 3468*1f6eb021SLiane Praza } else { 3469*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 3470*1f6eb021SLiane Praza *min = 0; 3471*1f6eb021SLiane Praza else 3472*1f6eb021SLiane Praza goto error; 3473*1f6eb021SLiane Praza } 3474*1f6eb021SLiane Praza 3475*1f6eb021SLiane Praza if (_read_single_value_from_pg(t->prt_pg, 3476*1f6eb021SLiane Praza SCF_PROPERTY_TM_CARDINALITY_MAX, &val_max) == 0) { 3477*1f6eb021SLiane Praza if (scf_value_get_count(val_max, max) < 0) 3478*1f6eb021SLiane Praza goto error; 3479*1f6eb021SLiane Praza } else { 3480*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 3481*1f6eb021SLiane Praza *max = UINT64_MAX; 3482*1f6eb021SLiane Praza else 3483*1f6eb021SLiane Praza goto error; 3484*1f6eb021SLiane Praza } 3485*1f6eb021SLiane Praza goto cleanup; 3486*1f6eb021SLiane Praza 3487*1f6eb021SLiane Praza error: 3488*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3489*1f6eb021SLiane Praza ret = -1; 3490*1f6eb021SLiane Praza } else switch (scf_error()) { 3491*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3492*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3493*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3494*1f6eb021SLiane Praza /*FALLTHROUGH*/ 3495*1f6eb021SLiane Praza 3496*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3497*1f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 3498*1f6eb021SLiane Praza ret = -1; 3499*1f6eb021SLiane Praza break; 3500*1f6eb021SLiane Praza 3501*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3502*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3503*1f6eb021SLiane Praza default: 3504*1f6eb021SLiane Praza assert(0); 3505*1f6eb021SLiane Praza abort(); 3506*1f6eb021SLiane Praza } 3507*1f6eb021SLiane Praza 3508*1f6eb021SLiane Praza cleanup: 3509*1f6eb021SLiane Praza scf_value_destroy(val_min); 3510*1f6eb021SLiane Praza scf_value_destroy(val_max); 3511*1f6eb021SLiane Praza 3512*1f6eb021SLiane Praza return (ret); 3513*1f6eb021SLiane Praza } 3514*1f6eb021SLiane Praza 3515*1f6eb021SLiane Praza /* 3516*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3517*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3518*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3519*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3520*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3521*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3522*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3523*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3524*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3525*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3526*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3527*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3528*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3529*1f6eb021SLiane Praza */ 3530*1f6eb021SLiane Praza int 3531*1f6eb021SLiane Praza scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t *t, scf_values_t *vals) 3532*1f6eb021SLiane Praza { 3533*1f6eb021SLiane Praza if (_read_astrings_values(t->prt_pg, 3534*1f6eb021SLiane Praza SCF_PROPERTY_INTERNAL_SEPARATORS, vals) == NULL) { 3535*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3536*1f6eb021SLiane Praza return (-1); 3537*1f6eb021SLiane Praza } else switch (scf_error()) { 3538*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3539*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3540*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3541*1f6eb021SLiane Praza /*FALLTHROUGH*/ 3542*1f6eb021SLiane Praza 3543*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3544*1f6eb021SLiane Praza return (-1); 3545*1f6eb021SLiane Praza 3546*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3547*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3548*1f6eb021SLiane Praza default: 3549*1f6eb021SLiane Praza assert(0); 3550*1f6eb021SLiane Praza abort(); 3551*1f6eb021SLiane Praza } 3552*1f6eb021SLiane Praza } else if (vals->value_count == 0) { 3553*1f6eb021SLiane Praza /* property has no value */ 3554*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 3555*1f6eb021SLiane Praza scf_values_destroy(vals); 3556*1f6eb021SLiane Praza return (-1); 3557*1f6eb021SLiane Praza } 3558*1f6eb021SLiane Praza 3559*1f6eb021SLiane Praza return (0); 3560*1f6eb021SLiane Praza } 3561*1f6eb021SLiane Praza 3562*1f6eb021SLiane Praza /* 3563*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3564*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3565*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3566*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3567*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3568*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3569*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3570*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3571*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3572*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3573*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3574*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3575*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3576*1f6eb021SLiane Praza */ 3577*1f6eb021SLiane Praza int 3578*1f6eb021SLiane Praza scf_tmpl_value_name_constraints(const scf_prop_tmpl_t *t, 3579*1f6eb021SLiane Praza scf_values_t *vals) 3580*1f6eb021SLiane Praza { 3581*1f6eb021SLiane Praza char **ret; 3582*1f6eb021SLiane Praza 3583*1f6eb021SLiane Praza ret = _read_astrings_values(t->prt_pg, 3584*1f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, vals); 3585*1f6eb021SLiane Praza 3586*1f6eb021SLiane Praza if (ret == NULL) { 3587*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3588*1f6eb021SLiane Praza return (-1); 3589*1f6eb021SLiane Praza } else switch (scf_error()) { 3590*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3591*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3592*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3593*1f6eb021SLiane Praza /*FALLTHROUGH*/ 3594*1f6eb021SLiane Praza 3595*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3596*1f6eb021SLiane Praza return (-1); 3597*1f6eb021SLiane Praza 3598*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3599*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3600*1f6eb021SLiane Praza default: 3601*1f6eb021SLiane Praza assert(0); 3602*1f6eb021SLiane Praza abort(); 3603*1f6eb021SLiane Praza } 3604*1f6eb021SLiane Praza } else if (vals->value_count == 0) { 3605*1f6eb021SLiane Praza /* property has no value */ 3606*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 3607*1f6eb021SLiane Praza scf_values_destroy(vals); 3608*1f6eb021SLiane Praza return (-1); 3609*1f6eb021SLiane Praza } 3610*1f6eb021SLiane Praza 3611*1f6eb021SLiane Praza return (0); 3612*1f6eb021SLiane Praza } 3613*1f6eb021SLiane Praza 3614*1f6eb021SLiane Praza /* 3615*1f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 3616*1f6eb021SLiane Praza * Caller is responsible for freeing returned pointer after use. 3617*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 3618*1f6eb021SLiane Praza * More tokens than the array size supplied. 3619*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3620*1f6eb021SLiane Praza */ 3621*1f6eb021SLiane Praza static void * 3622*1f6eb021SLiane Praza _separate_by_separator(char *string, const char *sep, char **array, int size) 3623*1f6eb021SLiane Praza { 3624*1f6eb021SLiane Praza char *str, *token; 3625*1f6eb021SLiane Praza char *lasts; 3626*1f6eb021SLiane Praza int n = 0; 3627*1f6eb021SLiane Praza 3628*1f6eb021SLiane Praza assert(array != NULL); 3629*1f6eb021SLiane Praza assert(string != NULL); 3630*1f6eb021SLiane Praza assert(sep != NULL); 3631*1f6eb021SLiane Praza assert(size > 0); 3632*1f6eb021SLiane Praza 3633*1f6eb021SLiane Praza str = strdup(string); 3634*1f6eb021SLiane Praza if (str == NULL) { 3635*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3636*1f6eb021SLiane Praza return (NULL); 3637*1f6eb021SLiane Praza } 3638*1f6eb021SLiane Praza 3639*1f6eb021SLiane Praza if ((array[n] = strtok_r(str, sep, &lasts)) == NULL) { 3640*1f6eb021SLiane Praza assert(0); 3641*1f6eb021SLiane Praza abort(); 3642*1f6eb021SLiane Praza } 3643*1f6eb021SLiane Praza 3644*1f6eb021SLiane Praza n++; 3645*1f6eb021SLiane Praza while ((token = strtok_r(NULL, sep, &lasts)) != NULL) { 3646*1f6eb021SLiane Praza if (n >= size) { 3647*1f6eb021SLiane Praza goto error; 3648*1f6eb021SLiane Praza } 3649*1f6eb021SLiane Praza array[n] = token; 3650*1f6eb021SLiane Praza n++; 3651*1f6eb021SLiane Praza } 3652*1f6eb021SLiane Praza if (n < size) { 3653*1f6eb021SLiane Praza goto error; 3654*1f6eb021SLiane Praza } 3655*1f6eb021SLiane Praza 3656*1f6eb021SLiane Praza return (str); 3657*1f6eb021SLiane Praza error: 3658*1f6eb021SLiane Praza free(str); 3659*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 3660*1f6eb021SLiane Praza return (NULL); 3661*1f6eb021SLiane Praza } 3662*1f6eb021SLiane Praza 3663*1f6eb021SLiane Praza /* 3664*1f6eb021SLiane Praza * check if name is among values of CHOICES_INCLUDE_VALUES 3665*1f6eb021SLiane Praza * return 0 if name is present, 1 name is not present, -1 on failure 3666*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3667*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3668*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3669*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3670*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3671*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3672*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3673*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3674*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3675*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3676*1f6eb021SLiane Praza */ 3677*1f6eb021SLiane Praza static int 3678*1f6eb021SLiane Praza _check_choices_include_values(scf_propertygroup_t *pg, const char *name) 3679*1f6eb021SLiane Praza { 3680*1f6eb021SLiane Praza int n = 0, r = 1; 3681*1f6eb021SLiane Praza char **ret; 3682*1f6eb021SLiane Praza scf_values_t vals; 3683*1f6eb021SLiane Praza 3684*1f6eb021SLiane Praza if ((ret = _read_astrings_values(pg, 3685*1f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES, &vals)) == NULL) { 3686*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3687*1f6eb021SLiane Praza return (-1); 3688*1f6eb021SLiane Praza } else switch (scf_error()) { 3689*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3690*1f6eb021SLiane Praza return (1); 3691*1f6eb021SLiane Praza 3692*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3693*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3694*1f6eb021SLiane Praza return (-1); 3695*1f6eb021SLiane Praza 3696*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3697*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3698*1f6eb021SLiane Praza default: 3699*1f6eb021SLiane Praza assert(0); 3700*1f6eb021SLiane Praza abort(); 3701*1f6eb021SLiane Praza } 3702*1f6eb021SLiane Praza } 3703*1f6eb021SLiane Praza 3704*1f6eb021SLiane Praza for (n = 0; n < vals.value_count; ++n) { 3705*1f6eb021SLiane Praza if (strcmp(name, ret[n]) == 0) { 3706*1f6eb021SLiane Praza r = 0; 3707*1f6eb021SLiane Praza break; 3708*1f6eb021SLiane Praza } 3709*1f6eb021SLiane Praza } 3710*1f6eb021SLiane Praza scf_values_destroy(&vals); 3711*1f6eb021SLiane Praza return (r); 3712*1f6eb021SLiane Praza } 3713*1f6eb021SLiane Praza 3714*1f6eb021SLiane Praza void 3715*1f6eb021SLiane Praza scf_count_ranges_destroy(scf_count_ranges_t *ranges) 3716*1f6eb021SLiane Praza { 3717*1f6eb021SLiane Praza if (ranges == NULL) 3718*1f6eb021SLiane Praza return; 3719*1f6eb021SLiane Praza 3720*1f6eb021SLiane Praza ranges->scr_num_ranges = 0; 3721*1f6eb021SLiane Praza free(ranges->scr_min); 3722*1f6eb021SLiane Praza free(ranges->scr_max); 3723*1f6eb021SLiane Praza ranges->scr_min = NULL; 3724*1f6eb021SLiane Praza ranges->scr_max = NULL; 3725*1f6eb021SLiane Praza } 3726*1f6eb021SLiane Praza 3727*1f6eb021SLiane Praza void 3728*1f6eb021SLiane Praza scf_int_ranges_destroy(scf_int_ranges_t *ranges) 3729*1f6eb021SLiane Praza { 3730*1f6eb021SLiane Praza if (ranges == NULL) 3731*1f6eb021SLiane Praza return; 3732*1f6eb021SLiane Praza 3733*1f6eb021SLiane Praza ranges->sir_num_ranges = 0; 3734*1f6eb021SLiane Praza free(ranges->sir_min); 3735*1f6eb021SLiane Praza free(ranges->sir_max); 3736*1f6eb021SLiane Praza ranges->sir_min = NULL; 3737*1f6eb021SLiane Praza ranges->sir_max = NULL; 3738*1f6eb021SLiane Praza } 3739*1f6eb021SLiane Praza 3740*1f6eb021SLiane Praza /* 3741*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3742*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3743*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3744*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 3745*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3746*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3747*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3748*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3749*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3750*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3751*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3752*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3753*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3754*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3755*1f6eb021SLiane Praza */ 3756*1f6eb021SLiane Praza static int 3757*1f6eb021SLiane Praza _scf_tmpl_get_count_ranges(const scf_prop_tmpl_t *t, const char *prop, 3758*1f6eb021SLiane Praza scf_count_ranges_t *ranges) 3759*1f6eb021SLiane Praza { 3760*1f6eb021SLiane Praza scf_values_t vals; 3761*1f6eb021SLiane Praza int i = 0; 3762*1f6eb021SLiane Praza char **ret; 3763*1f6eb021SLiane Praza char *one_range[2]; 3764*1f6eb021SLiane Praza char *endptr; 3765*1f6eb021SLiane Praza char *str = NULL; 3766*1f6eb021SLiane Praza uint64_t *min = NULL; 3767*1f6eb021SLiane Praza uint64_t *max = NULL; 3768*1f6eb021SLiane Praza 3769*1f6eb021SLiane Praza assert(ranges != NULL); 3770*1f6eb021SLiane Praza if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL) 3771*1f6eb021SLiane Praza goto error; 3772*1f6eb021SLiane Praza if (vals.value_count == 0) { 3773*1f6eb021SLiane Praza /* range values are empty */ 3774*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 3775*1f6eb021SLiane Praza goto cleanup; 3776*1f6eb021SLiane Praza } 3777*1f6eb021SLiane Praza 3778*1f6eb021SLiane Praza min = malloc(vals.value_count * sizeof (uint64_t)); 3779*1f6eb021SLiane Praza max = malloc(vals.value_count * sizeof (uint64_t)); 3780*1f6eb021SLiane Praza if (min == NULL || max == NULL) { 3781*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3782*1f6eb021SLiane Praza goto cleanup; 3783*1f6eb021SLiane Praza } 3784*1f6eb021SLiane Praza for (i = 0; i < vals.value_count; ++i) { 3785*1f6eb021SLiane Praza /* min and max should be separated by a "," */ 3786*1f6eb021SLiane Praza if ((str = _separate_by_separator(ret[i], ",", one_range, 3787*1f6eb021SLiane Praza 2)) == NULL) 3788*1f6eb021SLiane Praza goto cleanup; 3789*1f6eb021SLiane Praza errno = 0; 3790*1f6eb021SLiane Praza min[i] = strtoull(one_range[0], &endptr, 10); 3791*1f6eb021SLiane Praza if (errno != 0 || endptr == one_range[0] || *endptr) { 3792*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 3793*1f6eb021SLiane Praza goto cleanup; 3794*1f6eb021SLiane Praza } 3795*1f6eb021SLiane Praza errno = 0; 3796*1f6eb021SLiane Praza max[i] = strtoull(one_range[1], &endptr, 10); 3797*1f6eb021SLiane Praza if (errno != 0 || endptr == one_range[1] || *endptr) { 3798*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 3799*1f6eb021SLiane Praza goto cleanup; 3800*1f6eb021SLiane Praza } 3801*1f6eb021SLiane Praza if (min[i] > max[i]) { 3802*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 3803*1f6eb021SLiane Praza goto cleanup; 3804*1f6eb021SLiane Praza } 3805*1f6eb021SLiane Praza free(str); 3806*1f6eb021SLiane Praza str = NULL; 3807*1f6eb021SLiane Praza } 3808*1f6eb021SLiane Praza ranges->scr_num_ranges = vals.value_count; 3809*1f6eb021SLiane Praza ranges->scr_min = min; 3810*1f6eb021SLiane Praza ranges->scr_max = max; 3811*1f6eb021SLiane Praza scf_values_destroy(&vals); 3812*1f6eb021SLiane Praza return (0); 3813*1f6eb021SLiane Praza cleanup: 3814*1f6eb021SLiane Praza free(str); 3815*1f6eb021SLiane Praza free(min); 3816*1f6eb021SLiane Praza free(max); 3817*1f6eb021SLiane Praza scf_values_destroy(&vals); 3818*1f6eb021SLiane Praza error: 3819*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3820*1f6eb021SLiane Praza return (-1); 3821*1f6eb021SLiane Praza } else switch (scf_error()) { 3822*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3823*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3824*1f6eb021SLiane Praza /*FALLTHROUGH*/ 3825*1f6eb021SLiane Praza 3826*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3827*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3828*1f6eb021SLiane Praza return (-1); 3829*1f6eb021SLiane Praza 3830*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3831*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3832*1f6eb021SLiane Praza default: 3833*1f6eb021SLiane Praza assert(0); 3834*1f6eb021SLiane Praza abort(); 3835*1f6eb021SLiane Praza } 3836*1f6eb021SLiane Praza /*NOTREACHED*/ 3837*1f6eb021SLiane Praza } 3838*1f6eb021SLiane Praza 3839*1f6eb021SLiane Praza /* 3840*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3841*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3842*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3843*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 3844*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3845*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3846*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3847*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3848*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3849*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3850*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3851*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3852*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3853*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3854*1f6eb021SLiane Praza */ 3855*1f6eb021SLiane Praza static int 3856*1f6eb021SLiane Praza _scf_tmpl_get_int_ranges(const scf_prop_tmpl_t *t, const char *prop, 3857*1f6eb021SLiane Praza scf_int_ranges_t *ranges) 3858*1f6eb021SLiane Praza { 3859*1f6eb021SLiane Praza scf_values_t vals; 3860*1f6eb021SLiane Praza int n = 0; 3861*1f6eb021SLiane Praza char **ret; 3862*1f6eb021SLiane Praza char *one_range[2]; 3863*1f6eb021SLiane Praza char *endptr; 3864*1f6eb021SLiane Praza char *str = NULL; 3865*1f6eb021SLiane Praza int64_t *min = NULL; 3866*1f6eb021SLiane Praza int64_t *max = NULL; 3867*1f6eb021SLiane Praza 3868*1f6eb021SLiane Praza assert(ranges != NULL); 3869*1f6eb021SLiane Praza if ((ret = _read_astrings_values(t->prt_pg, prop, &vals)) == NULL) 3870*1f6eb021SLiane Praza goto error; 3871*1f6eb021SLiane Praza if (vals.value_count == 0) { 3872*1f6eb021SLiane Praza /* range values are empty */ 3873*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 3874*1f6eb021SLiane Praza goto cleanup; 3875*1f6eb021SLiane Praza } 3876*1f6eb021SLiane Praza 3877*1f6eb021SLiane Praza min = malloc(vals.value_count * sizeof (int64_t)); 3878*1f6eb021SLiane Praza max = malloc(vals.value_count * sizeof (int64_t)); 3879*1f6eb021SLiane Praza if (min == NULL || max == NULL) { 3880*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3881*1f6eb021SLiane Praza goto cleanup; 3882*1f6eb021SLiane Praza } 3883*1f6eb021SLiane Praza while (n < vals.value_count) { 3884*1f6eb021SLiane Praza /* min and max should be separated by a "," */ 3885*1f6eb021SLiane Praza if ((str = _separate_by_separator(ret[n], ",", one_range, 2)) 3886*1f6eb021SLiane Praza == NULL) 3887*1f6eb021SLiane Praza goto cleanup; 3888*1f6eb021SLiane Praza errno = 0; 3889*1f6eb021SLiane Praza min[n] = strtoll(one_range[0], &endptr, 10); 3890*1f6eb021SLiane Praza if (errno != 0 || endptr == one_range[0] || *endptr) { 3891*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 3892*1f6eb021SLiane Praza goto cleanup; 3893*1f6eb021SLiane Praza } 3894*1f6eb021SLiane Praza errno = 0; 3895*1f6eb021SLiane Praza max[n] = strtoll(one_range[1], &endptr, 10); 3896*1f6eb021SLiane Praza if (errno != 0 || endptr == one_range[1] || *endptr) { 3897*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 3898*1f6eb021SLiane Praza goto cleanup; 3899*1f6eb021SLiane Praza } 3900*1f6eb021SLiane Praza if (min[n] > max[n]) { 3901*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3902*1f6eb021SLiane Praza goto cleanup; 3903*1f6eb021SLiane Praza } 3904*1f6eb021SLiane Praza ++n; 3905*1f6eb021SLiane Praza free(str); 3906*1f6eb021SLiane Praza str = NULL; 3907*1f6eb021SLiane Praza } 3908*1f6eb021SLiane Praza ranges->sir_num_ranges = vals.value_count; 3909*1f6eb021SLiane Praza ranges->sir_min = min; 3910*1f6eb021SLiane Praza ranges->sir_max = max; 3911*1f6eb021SLiane Praza scf_values_destroy(&vals); 3912*1f6eb021SLiane Praza return (0); 3913*1f6eb021SLiane Praza cleanup: 3914*1f6eb021SLiane Praza free(str); 3915*1f6eb021SLiane Praza free(min); 3916*1f6eb021SLiane Praza free(max); 3917*1f6eb021SLiane Praza scf_values_destroy(&vals); 3918*1f6eb021SLiane Praza error: 3919*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 3920*1f6eb021SLiane Praza return (-1); 3921*1f6eb021SLiane Praza } else switch (scf_error()) { 3922*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 3923*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 3924*1f6eb021SLiane Praza /*FALLTHROUGH*/ 3925*1f6eb021SLiane Praza 3926*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 3927*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 3928*1f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 3929*1f6eb021SLiane Praza return (-1); 3930*1f6eb021SLiane Praza 3931*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 3932*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 3933*1f6eb021SLiane Praza default: 3934*1f6eb021SLiane Praza assert(0); 3935*1f6eb021SLiane Praza abort(); 3936*1f6eb021SLiane Praza } 3937*1f6eb021SLiane Praza /*NOTREACHED*/ 3938*1f6eb021SLiane Praza } 3939*1f6eb021SLiane Praza 3940*1f6eb021SLiane Praza /* 3941*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3942*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3943*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3944*1f6eb021SLiane Praza * SCF_ERROR_CONSTRAINT_VIOLATED 3945*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3946*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3947*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3948*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3949*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3950*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3951*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3952*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 3953*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 3954*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 3955*1f6eb021SLiane Praza */ 3956*1f6eb021SLiane Praza int 3957*1f6eb021SLiane Praza scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t *t, 3958*1f6eb021SLiane Praza scf_count_ranges_t *ranges) 3959*1f6eb021SLiane Praza { 3960*1f6eb021SLiane Praza return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE, 3961*1f6eb021SLiane Praza ranges)); 3962*1f6eb021SLiane Praza } 3963*1f6eb021SLiane Praza 3964*1f6eb021SLiane Praza int 3965*1f6eb021SLiane Praza scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t *t, 3966*1f6eb021SLiane Praza scf_int_ranges_t *ranges) 3967*1f6eb021SLiane Praza { 3968*1f6eb021SLiane Praza return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CONSTRAINT_RANGE, 3969*1f6eb021SLiane Praza ranges)); 3970*1f6eb021SLiane Praza } 3971*1f6eb021SLiane Praza 3972*1f6eb021SLiane Praza int 3973*1f6eb021SLiane Praza scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t *t, 3974*1f6eb021SLiane Praza scf_count_ranges_t *ranges) 3975*1f6eb021SLiane Praza { 3976*1f6eb021SLiane Praza return (_scf_tmpl_get_count_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE, 3977*1f6eb021SLiane Praza ranges)); 3978*1f6eb021SLiane Praza } 3979*1f6eb021SLiane Praza 3980*1f6eb021SLiane Praza int 3981*1f6eb021SLiane Praza scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t *t, 3982*1f6eb021SLiane Praza scf_int_ranges_t *ranges) 3983*1f6eb021SLiane Praza { 3984*1f6eb021SLiane Praza return (_scf_tmpl_get_int_ranges(t, SCF_PROPERTY_TM_CHOICES_RANGE, 3985*1f6eb021SLiane Praza ranges)); 3986*1f6eb021SLiane Praza } 3987*1f6eb021SLiane Praza 3988*1f6eb021SLiane Praza /* 3989*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 3990*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 3991*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 3992*1f6eb021SLiane Praza * SCF_ERROR_DELETED 3993*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 3994*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 3995*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 3996*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 3997*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 3998*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 3999*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 4000*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 4001*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 4002*1f6eb021SLiane Praza */ 4003*1f6eb021SLiane Praza int 4004*1f6eb021SLiane Praza scf_tmpl_value_name_choices(const scf_prop_tmpl_t *t, scf_values_t *vals) 4005*1f6eb021SLiane Praza { 4006*1f6eb021SLiane Praza int c_flag = 0; /* have not read any value yet */ 4007*1f6eb021SLiane Praza int r; 4008*1f6eb021SLiane Praza char **ret; 4009*1f6eb021SLiane Praza 4010*1f6eb021SLiane Praza /* First, look for explicitly declared choices. */ 4011*1f6eb021SLiane Praza if ((ret = _read_astrings_values(t->prt_pg, 4012*1f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_NAME, vals)) != NULL) { 4013*1f6eb021SLiane Praza c_flag = 1; 4014*1f6eb021SLiane Praza } else if (scf_error() != SCF_ERROR_NOT_FOUND) { 4015*1f6eb021SLiane Praza goto error; 4016*1f6eb021SLiane Praza } 4017*1f6eb021SLiane Praza 4018*1f6eb021SLiane Praza /* Next, check for choices included by 'values'. */ 4019*1f6eb021SLiane Praza if ((r = _check_choices_include_values(t->prt_pg, "values")) == 0) { 4020*1f6eb021SLiane Praza /* read values_name */ 4021*1f6eb021SLiane Praza if (c_flag == 1) 4022*1f6eb021SLiane Praza /* append values */ 4023*1f6eb021SLiane Praza ret = _append_astrings_values(t->prt_pg, 4024*1f6eb021SLiane Praza SCF_PROPERTY_TM_VALUES_NAME, vals); 4025*1f6eb021SLiane Praza else 4026*1f6eb021SLiane Praza /* read values */ 4027*1f6eb021SLiane Praza ret = _read_astrings_values(t->prt_pg, 4028*1f6eb021SLiane Praza SCF_PROPERTY_TM_VALUES_NAME, vals); 4029*1f6eb021SLiane Praza if (ret != NULL) { 4030*1f6eb021SLiane Praza c_flag = 1; 4031*1f6eb021SLiane Praza } else if (scf_error() != SCF_ERROR_NOT_FOUND) { 4032*1f6eb021SLiane Praza goto error; 4033*1f6eb021SLiane Praza } 4034*1f6eb021SLiane Praza } else if (r == -1) { 4035*1f6eb021SLiane Praza goto error; 4036*1f6eb021SLiane Praza } 4037*1f6eb021SLiane Praza 4038*1f6eb021SLiane Praza /* Finally check for choices included by 'constraints'. */ 4039*1f6eb021SLiane Praza if ((r = _check_choices_include_values(t->prt_pg, "constraints")) == 4040*1f6eb021SLiane Praza 0) { 4041*1f6eb021SLiane Praza /* read constraint_name */ 4042*1f6eb021SLiane Praza if (c_flag == 1) 4043*1f6eb021SLiane Praza /* append values */ 4044*1f6eb021SLiane Praza ret = _append_astrings_values(t->prt_pg, 4045*1f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, vals); 4046*1f6eb021SLiane Praza else 4047*1f6eb021SLiane Praza /* read values */ 4048*1f6eb021SLiane Praza ret = _read_astrings_values(t->prt_pg, 4049*1f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, vals); 4050*1f6eb021SLiane Praza if (ret != NULL) { 4051*1f6eb021SLiane Praza c_flag = 1; 4052*1f6eb021SLiane Praza } else if (scf_error() != SCF_ERROR_NOT_FOUND) { 4053*1f6eb021SLiane Praza goto error; 4054*1f6eb021SLiane Praza } 4055*1f6eb021SLiane Praza } else if (r == -1) { 4056*1f6eb021SLiane Praza goto error; 4057*1f6eb021SLiane Praza } 4058*1f6eb021SLiane Praza 4059*1f6eb021SLiane Praza if (c_flag == 0 || vals->value_count == 0) { 4060*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 4061*1f6eb021SLiane Praza return (-1); 4062*1f6eb021SLiane Praza } 4063*1f6eb021SLiane Praza 4064*1f6eb021SLiane Praza return (0); 4065*1f6eb021SLiane Praza 4066*1f6eb021SLiane Praza error: 4067*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 4068*1f6eb021SLiane Praza return (-1); 4069*1f6eb021SLiane Praza } else switch (scf_error()) { 4070*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 4071*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 4072*1f6eb021SLiane Praza return (-1); 4073*1f6eb021SLiane Praza 4074*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 4075*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 4076*1f6eb021SLiane Praza default: 4077*1f6eb021SLiane Praza assert(0); 4078*1f6eb021SLiane Praza abort(); 4079*1f6eb021SLiane Praza } 4080*1f6eb021SLiane Praza /*NOTREACHED*/ 4081*1f6eb021SLiane Praza } 4082*1f6eb021SLiane Praza 4083*1f6eb021SLiane Praza void 4084*1f6eb021SLiane Praza scf_values_destroy(scf_values_t *vals) 4085*1f6eb021SLiane Praza { 4086*1f6eb021SLiane Praza int i; 4087*1f6eb021SLiane Praza char **items = NULL; 4088*1f6eb021SLiane Praza char **str = vals->values_as_strings; 4089*1f6eb021SLiane Praza 4090*1f6eb021SLiane Praza if (vals == NULL) 4091*1f6eb021SLiane Praza return; 4092*1f6eb021SLiane Praza 4093*1f6eb021SLiane Praza /* free values */ 4094*1f6eb021SLiane Praza switch (vals->value_type) { 4095*1f6eb021SLiane Praza case SCF_TYPE_BOOLEAN: 4096*1f6eb021SLiane Praza free(vals->values.v_boolean); 4097*1f6eb021SLiane Praza break; 4098*1f6eb021SLiane Praza case SCF_TYPE_COUNT: 4099*1f6eb021SLiane Praza free(vals->values.v_count); 4100*1f6eb021SLiane Praza break; 4101*1f6eb021SLiane Praza case SCF_TYPE_INTEGER: 4102*1f6eb021SLiane Praza free(vals->values.v_integer); 4103*1f6eb021SLiane Praza break; 4104*1f6eb021SLiane Praza case SCF_TYPE_ASTRING: 4105*1f6eb021SLiane Praza items = vals->values.v_astring; 4106*1f6eb021SLiane Praza str = NULL; 4107*1f6eb021SLiane Praza break; 4108*1f6eb021SLiane Praza case SCF_TYPE_USTRING: 4109*1f6eb021SLiane Praza items = vals->values.v_ustring; 4110*1f6eb021SLiane Praza str = NULL; 4111*1f6eb021SLiane Praza break; 4112*1f6eb021SLiane Praza case SCF_TYPE_OPAQUE: 4113*1f6eb021SLiane Praza items = vals->values.v_opaque; 4114*1f6eb021SLiane Praza str = NULL; 4115*1f6eb021SLiane Praza break; 4116*1f6eb021SLiane Praza case SCF_TYPE_TIME: 4117*1f6eb021SLiane Praza free(vals->values.v_time); 4118*1f6eb021SLiane Praza break; 4119*1f6eb021SLiane Praza default: 4120*1f6eb021SLiane Praza assert(0); 4121*1f6eb021SLiane Praza abort(); 4122*1f6eb021SLiane Praza } 4123*1f6eb021SLiane Praza for (i = 0; i < vals->value_count; ++i) { 4124*1f6eb021SLiane Praza if (items != NULL) 4125*1f6eb021SLiane Praza free(items[i]); 4126*1f6eb021SLiane Praza if (str != NULL) 4127*1f6eb021SLiane Praza free(str[i]); 4128*1f6eb021SLiane Praza } 4129*1f6eb021SLiane Praza vals->value_count = 0; 4130*1f6eb021SLiane Praza free(items); 4131*1f6eb021SLiane Praza free(str); 4132*1f6eb021SLiane Praza } 4133*1f6eb021SLiane Praza 4134*1f6eb021SLiane Praza /* 4135*1f6eb021SLiane Praza * char *_make_value_name() 4136*1f6eb021SLiane Praza * 4137*1f6eb021SLiane Praza * Construct the prefix for a value common name or value description property. 4138*1f6eb021SLiane Praza * It takes the form: 4139*1f6eb021SLiane Praza * value_<BASE32 name>_<common_name|description>_ 4140*1f6eb021SLiane Praza * This is then combined with a localized suffix by the caller to look 4141*1f6eb021SLiane Praza * up the property in the repository: 4142*1f6eb021SLiane Praza * value_<BASE32 name>_<common_name|description>_<lang> 4143*1f6eb021SLiane Praza * 4144*1f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 4145*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 4146*1f6eb021SLiane Praza * Name isn't short enough make a value name with. 4147*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4148*1f6eb021SLiane Praza */ 4149*1f6eb021SLiane Praza static char * 4150*1f6eb021SLiane Praza _make_value_name(char *desc_name, const char *value) 4151*1f6eb021SLiane Praza { 4152*1f6eb021SLiane Praza char *name = NULL; 4153*1f6eb021SLiane Praza char *encoded = NULL; 4154*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 4155*1f6eb021SLiane Praza 4156*1f6eb021SLiane Praza name = malloc(sz); 4157*1f6eb021SLiane Praza encoded = malloc(sz); 4158*1f6eb021SLiane Praza if (name == NULL || encoded == NULL) { 4159*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4160*1f6eb021SLiane Praza free(name); 4161*1f6eb021SLiane Praza free(encoded); 4162*1f6eb021SLiane Praza return (NULL); 4163*1f6eb021SLiane Praza } 4164*1f6eb021SLiane Praza 4165*1f6eb021SLiane Praza if (scf_encode32(value, strlen(value), encoded, sz, NULL, 4166*1f6eb021SLiane Praza SCF_ENCODE32_PAD) != 0) { 4167*1f6eb021SLiane Praza /* Shouldn't happen. */ 4168*1f6eb021SLiane Praza assert(0); 4169*1f6eb021SLiane Praza } 4170*1f6eb021SLiane Praza 4171*1f6eb021SLiane Praza (void) strlcpy(name, SCF_PROPERTY_TM_VALUE_PREFIX, sz); 4172*1f6eb021SLiane Praza 4173*1f6eb021SLiane Praza if (strlcat(name, encoded, sz) >= sz) { 4174*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 4175*1f6eb021SLiane Praza free(name); 4176*1f6eb021SLiane Praza free(encoded); 4177*1f6eb021SLiane Praza return (NULL); 4178*1f6eb021SLiane Praza } 4179*1f6eb021SLiane Praza 4180*1f6eb021SLiane Praza if (strlcat(name, "_", sz) >= sz) { 4181*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 4182*1f6eb021SLiane Praza free(name); 4183*1f6eb021SLiane Praza free(encoded); 4184*1f6eb021SLiane Praza return (NULL); 4185*1f6eb021SLiane Praza } 4186*1f6eb021SLiane Praza 4187*1f6eb021SLiane Praza if (strlcat(name, desc_name, sz) >= sz) { 4188*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 4189*1f6eb021SLiane Praza free(name); 4190*1f6eb021SLiane Praza free(encoded); 4191*1f6eb021SLiane Praza return (NULL); 4192*1f6eb021SLiane Praza } 4193*1f6eb021SLiane Praza 4194*1f6eb021SLiane Praza if (strlcat(name, "_", sz) >= sz) { 4195*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 4196*1f6eb021SLiane Praza free(name); 4197*1f6eb021SLiane Praza free(encoded); 4198*1f6eb021SLiane Praza return (NULL); 4199*1f6eb021SLiane Praza } 4200*1f6eb021SLiane Praza 4201*1f6eb021SLiane Praza free(encoded); 4202*1f6eb021SLiane Praza return (name); 4203*1f6eb021SLiane Praza } 4204*1f6eb021SLiane Praza 4205*1f6eb021SLiane Praza /* 4206*1f6eb021SLiane Praza * ssize_t scf_tmpl_value_common_name() 4207*1f6eb021SLiane Praza * 4208*1f6eb021SLiane Praza * Populates "out" with an allocated string containing the value's 4209*1f6eb021SLiane Praza * common name. Returns the size of the string on successful return. 4210*1f6eb021SLiane Praza * out must be freed with free() on successful return. 4211*1f6eb021SLiane Praza * 4212*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 4213*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 4214*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 4215*1f6eb021SLiane Praza * SCF_ERROR_DELETED 4216*1f6eb021SLiane Praza * Property group was deleted. 4217*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 4218*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 4219*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 4220*1f6eb021SLiane Praza * name not a valid property name 4221*1f6eb021SLiane Praza * name and locale are too long to make a property name 4222*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4223*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 4224*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 4225*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 4226*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 4227*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 4228*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 4229*1f6eb021SLiane Praza * property is not SCF_TYPE_ASTRING has more than one value. 4230*1f6eb021SLiane Praza */ 4231*1f6eb021SLiane Praza ssize_t 4232*1f6eb021SLiane Praza scf_tmpl_value_common_name(const scf_prop_tmpl_t *t, const char *locale, 4233*1f6eb021SLiane Praza const char *value, char **out) 4234*1f6eb021SLiane Praza { 4235*1f6eb021SLiane Praza char *value_name = NULL; 4236*1f6eb021SLiane Praza 4237*1f6eb021SLiane Praza value_name = _make_value_name("common_name", value); 4238*1f6eb021SLiane Praza if (value_name == NULL) 4239*1f6eb021SLiane Praza return (-1); 4240*1f6eb021SLiane Praza 4241*1f6eb021SLiane Praza *out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale); 4242*1f6eb021SLiane Praza 4243*1f6eb021SLiane Praza free(value_name); 4244*1f6eb021SLiane Praza 4245*1f6eb021SLiane Praza if (*out == NULL) 4246*1f6eb021SLiane Praza return (-1); 4247*1f6eb021SLiane Praza 4248*1f6eb021SLiane Praza return (strlen(*out)); 4249*1f6eb021SLiane Praza } 4250*1f6eb021SLiane Praza 4251*1f6eb021SLiane Praza /* 4252*1f6eb021SLiane Praza * ssize_t scf_tmpl_value_description() 4253*1f6eb021SLiane Praza * 4254*1f6eb021SLiane Praza * Populates "out" with an allocated string containing the value's 4255*1f6eb021SLiane Praza * description. Returns the size of the string on successful return. 4256*1f6eb021SLiane Praza * out must be freed with free() on successful return. 4257*1f6eb021SLiane Praza * 4258*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 4259*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 4260*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 4261*1f6eb021SLiane Praza * SCF_ERROR_DELETED 4262*1f6eb021SLiane Praza * Property group was deleted. 4263*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 4264*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 4265*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 4266*1f6eb021SLiane Praza * name not a valid property name 4267*1f6eb021SLiane Praza * name and locale are too long to make a property name 4268*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4269*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 4270*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 4271*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 4272*1f6eb021SLiane Praza * Property doesn't exist or exists and has no value. 4273*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 4274*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 4275*1f6eb021SLiane Praza * property is not SCF_TYPE_ASTRING has more than one value. 4276*1f6eb021SLiane Praza */ 4277*1f6eb021SLiane Praza ssize_t 4278*1f6eb021SLiane Praza scf_tmpl_value_description(const scf_prop_tmpl_t *t, const char *locale, 4279*1f6eb021SLiane Praza const char *value, char **out) 4280*1f6eb021SLiane Praza { 4281*1f6eb021SLiane Praza char *value_name = NULL; 4282*1f6eb021SLiane Praza 4283*1f6eb021SLiane Praza value_name = _make_value_name("description", value); 4284*1f6eb021SLiane Praza if (value_name == NULL) 4285*1f6eb021SLiane Praza return (-1); 4286*1f6eb021SLiane Praza 4287*1f6eb021SLiane Praza 4288*1f6eb021SLiane Praza *out = _read_localized_astring_from_pg(t->prt_pg, value_name, locale); 4289*1f6eb021SLiane Praza 4290*1f6eb021SLiane Praza free(value_name); 4291*1f6eb021SLiane Praza 4292*1f6eb021SLiane Praza if (*out == NULL) 4293*1f6eb021SLiane Praza return (-1); 4294*1f6eb021SLiane Praza 4295*1f6eb021SLiane Praza return (strlen(*out)); 4296*1f6eb021SLiane Praza } 4297*1f6eb021SLiane Praza 4298*1f6eb021SLiane Praza /* 4299*1f6eb021SLiane Praza * Templates error messages format, in human readable form. 4300*1f6eb021SLiane Praza * Each line is one error item: 4301*1f6eb021SLiane Praza * 4302*1f6eb021SLiane Praza * prefix error message 4303*1f6eb021SLiane Praza * FMRI="err->te_errs->tes_fmri" 4304*1f6eb021SLiane Praza * Property group="err->te_pg_name" 4305*1f6eb021SLiane Praza * Property name="err->te_prop_name" 4306*1f6eb021SLiane Praza * expected value 1="err->te_ev1" 4307*1f6eb021SLiane Praza * expected value 2="err->te_ev2" 4308*1f6eb021SLiane Praza * actual value="err->te_actual" 4309*1f6eb021SLiane Praza * Tempalte source="err->te_tmpl_fmri" 4310*1f6eb021SLiane Praza * pg_pattern name="err->tmpl_pg_name" 4311*1f6eb021SLiane Praza * pg_pattern type="err->tmpl_pg_type" 4312*1f6eb021SLiane Praza * prop_pattern name="err->tmpl_prop_name" 4313*1f6eb021SLiane Praza * prop_pattern type="err->tmpl_prop_type" 4314*1f6eb021SLiane Praza * 4315*1f6eb021SLiane Praza * To add a new error type, include scf_tmpl_error_type_t in libscf.h 4316*1f6eb021SLiane Praza * add one entry in em_desc[], and update the functions pointed by the 4317*1f6eb021SLiane Praza * _tmpl_error_access array with the new error code. Also, update the 4318*1f6eb021SLiane Praza * scf_tmpl_error_* functions to provide access to desired 4319*1f6eb021SLiane Praza * scf_tmpl_error_t fields. 4320*1f6eb021SLiane Praza * 4321*1f6eb021SLiane Praza * To add a new error item, add a new field to scf_tmpl_error_t, a new field 4322*1f6eb021SLiane Praza * in _scf_tmpl_error_desc or a new non-error-dependent string, add a new entry 4323*1f6eb021SLiane Praza * in _tmpl_error_access array and create the appropriate get_val, get_desc 4324*1f6eb021SLiane Praza * functions. 4325*1f6eb021SLiane Praza * 4326*1f6eb021SLiane Praza * Changes to both the validation logic and the error types and items must 4327*1f6eb021SLiane Praza * be coordinated with the code in svccfg to ensure both libscf and svccfg's 4328*1f6eb021SLiane Praza * manifest validation validate the same things. 4329*1f6eb021SLiane Praza */ 4330*1f6eb021SLiane Praza 4331*1f6eb021SLiane Praza /* 4332*1f6eb021SLiane Praza * Container for all template errors on a validated object. 4333*1f6eb021SLiane Praza */ 4334*1f6eb021SLiane Praza struct scf_tmpl_errors { 4335*1f6eb021SLiane Praza int tes_index; 4336*1f6eb021SLiane Praza int tes_num_errs; 4337*1f6eb021SLiane Praza scf_tmpl_error_t **tes_errs; 4338*1f6eb021SLiane Praza int tes_errs_size; 4339*1f6eb021SLiane Praza const char *tes_fmri; 4340*1f6eb021SLiane Praza const char *tes_prefix; 4341*1f6eb021SLiane Praza int tes_flag; /* if set, scf_tmpl_error_destroy */ 4342*1f6eb021SLiane Praza /* will free strings in tes_errs */ 4343*1f6eb021SLiane Praza }; 4344*1f6eb021SLiane Praza 4345*1f6eb021SLiane Praza /* 4346*1f6eb021SLiane Praza * Templates error-dependent labels 4347*1f6eb021SLiane Praza */ 4348*1f6eb021SLiane Praza struct _scf_tmpl_error_desc { 4349*1f6eb021SLiane Praza const char *em_msg; 4350*1f6eb021SLiane Praza const char *em_ev1; 4351*1f6eb021SLiane Praza const char *em_ev2; 4352*1f6eb021SLiane Praza const char *em_actual; 4353*1f6eb021SLiane Praza }; 4354*1f6eb021SLiane Praza 4355*1f6eb021SLiane Praza /* 4356*1f6eb021SLiane Praza * This array MUST be kept in synch with the template error definition of 4357*1f6eb021SLiane Praza * scf_tmpl_error_type_t in libscf.h 4358*1f6eb021SLiane Praza */ 4359*1f6eb021SLiane Praza static struct _scf_tmpl_error_desc em_desc[] = { 4360*1f6eb021SLiane Praza /* SCF_TERR_MISSING_PG */ 4361*1f6eb021SLiane Praza { "Required property group missing", "Name of missing property group", 4362*1f6eb021SLiane Praza "Type of missing property group", NULL }, 4363*1f6eb021SLiane Praza /* SCF_TERR_WRONG_PG_TYPE */ 4364*1f6eb021SLiane Praza { "Property group has bad type", "Specified type", NULL, 4365*1f6eb021SLiane Praza "Actual type" }, 4366*1f6eb021SLiane Praza /* SCF_TERR_MISSING_PROP */ 4367*1f6eb021SLiane Praza { "Required property missing", "Name of missing property", NULL, NULL }, 4368*1f6eb021SLiane Praza /* SCF_TERR_WRONG_PROP_TYPE */ 4369*1f6eb021SLiane Praza { "Property has bad type", "Specified property type", NULL, 4370*1f6eb021SLiane Praza "Actual property type" }, 4371*1f6eb021SLiane Praza /* SCF_TERR_CARDINALITY_VIOLATION */ 4372*1f6eb021SLiane Praza { "Number of property values violates cardinality restriction", 4373*1f6eb021SLiane Praza "Cardinality minimum", "Cardinality maximum", 4374*1f6eb021SLiane Praza "Actual number of values" }, 4375*1f6eb021SLiane Praza /* SCF_TERR_VALUE_CONSTRAINT_VIOLATED */ 4376*1f6eb021SLiane Praza { "Property has illegal value", NULL, NULL, "Illegal value" }, 4377*1f6eb021SLiane Praza /* SCF_TERR_RANGE_VIOLATION */ 4378*1f6eb021SLiane Praza { "Property value is out of range", NULL, NULL, "Actual value" }, 4379*1f6eb021SLiane Praza /* SCF_TERR_PG_REDEFINE */ 4380*1f6eb021SLiane Praza { "Instance redefines pg_pattern", "Instance pg_pattern name", 4381*1f6eb021SLiane Praza "Instance pg_pattern type", NULL }, 4382*1f6eb021SLiane Praza /* SCF_TERR_PROP_TYPE_MISMATCH */ 4383*1f6eb021SLiane Praza { "Property type and value type mismatch", NULL, NULL, "Value type" }, 4384*1f6eb021SLiane Praza /* SCF_TERR_VALUE_OUT_OF_RANGE */ 4385*1f6eb021SLiane Praza { "Value is out of range", NULL, NULL, "Value" }, 4386*1f6eb021SLiane Praza /* SCF_TERR_INVALID_VALUE */ 4387*1f6eb021SLiane Praza { "Value is not valid", NULL, NULL, "Value" }, 4388*1f6eb021SLiane Praza /* SCF_TERR_PG_PATTERN_CONFLICT */ 4389*1f6eb021SLiane Praza { "Conflicting pg_pattern specifications", "Template source", 4390*1f6eb021SLiane Praza "pg_pattern name", "pg_pattern type" }, 4391*1f6eb021SLiane Praza /* SCF_TERR_PROP_PATTERN_CONFLICT */ 4392*1f6eb021SLiane Praza { "Conflicting prop_pattern specifications", "Template source", 4393*1f6eb021SLiane Praza "prop_pattern name", "prop_pattern type" }, 4394*1f6eb021SLiane Praza /* SCF_TERR_GENERAL_REDEFINE */ 4395*1f6eb021SLiane Praza { "Service or instance pg_pattern redefines a global or restarter " 4396*1f6eb021SLiane Praza "pg_pattern", "Template source", "pg_pattern name", 4397*1f6eb021SLiane Praza "pg_pattern type" }, 4398*1f6eb021SLiane Praza /* SCF_TERR_INCLUDE_VALUES */ 4399*1f6eb021SLiane Praza { "Missing constraints or values for include_values element", 4400*1f6eb021SLiane Praza "include_values type", NULL, NULL }, 4401*1f6eb021SLiane Praza /* SCF_TERR_PG_PATTERN_INCOMPLETE */ 4402*1f6eb021SLiane Praza { "Required pg_pattern is missing a name or type attribute", 4403*1f6eb021SLiane Praza NULL, NULL, NULL }, 4404*1f6eb021SLiane Praza /* SCF_TERR_PROP_PATTERN_INCOMPLETE */ 4405*1f6eb021SLiane Praza { "Required prop_pattern is missing a type attribute", 4406*1f6eb021SLiane Praza NULL, NULL, NULL } 4407*1f6eb021SLiane Praza }; 4408*1f6eb021SLiane Praza 4409*1f6eb021SLiane Praza /* 4410*1f6eb021SLiane Praza * Templates non error-dependent labels 4411*1f6eb021SLiane Praza */ 4412*1f6eb021SLiane Praza static const char *em_fmri = "FMRI"; 4413*1f6eb021SLiane Praza static const char *em_pg_name = "Property group"; 4414*1f6eb021SLiane Praza static const char *em_prop_name = "Property name"; 4415*1f6eb021SLiane Praza static const char *em_tmpl_fmri = "Template source"; 4416*1f6eb021SLiane Praza static const char *em_tmpl_pg_name = "pg_pattern name"; 4417*1f6eb021SLiane Praza static const char *em_tmpl_pg_type = "pg_pattern type"; 4418*1f6eb021SLiane Praza static const char *em_tmpl_prop_name = "prop_pattern name"; 4419*1f6eb021SLiane Praza static const char *em_tmpl_prop_type = "prop_pattern type"; 4420*1f6eb021SLiane Praza 4421*1f6eb021SLiane Praza static const char * 4422*1f6eb021SLiane Praza _get_fmri_desc(scf_tmpl_error_t *err) 4423*1f6eb021SLiane Praza { 4424*1f6eb021SLiane Praza switch (err->te_type) { 4425*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4426*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4427*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4428*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4429*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4430*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4431*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4432*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4433*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4434*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4435*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4436*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_fmri)); 4437*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4438*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4439*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4440*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4441*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4442*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4443*1f6eb021SLiane Praza default: 4444*1f6eb021SLiane Praza return (NULL); 4445*1f6eb021SLiane Praza } 4446*1f6eb021SLiane Praza } 4447*1f6eb021SLiane Praza 4448*1f6eb021SLiane Praza static const char * 4449*1f6eb021SLiane Praza _get_pg_name_desc(scf_tmpl_error_t *err) 4450*1f6eb021SLiane Praza { 4451*1f6eb021SLiane Praza switch (err->te_type) { 4452*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4453*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4454*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4455*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4456*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4457*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4458*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_pg_name)); 4459*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4460*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4461*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4462*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4463*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4464*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4465*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4466*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4467*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4468*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4469*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4470*1f6eb021SLiane Praza default: 4471*1f6eb021SLiane Praza return (NULL); 4472*1f6eb021SLiane Praza } 4473*1f6eb021SLiane Praza } 4474*1f6eb021SLiane Praza 4475*1f6eb021SLiane Praza static const char * 4476*1f6eb021SLiane Praza _get_prop_name_desc(scf_tmpl_error_t *err) 4477*1f6eb021SLiane Praza { 4478*1f6eb021SLiane Praza switch (err->te_type) { 4479*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4480*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4481*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4482*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4483*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_prop_name)); 4484*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4485*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4486*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4487*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4488*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4489*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4490*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4491*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4492*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4493*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4494*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4495*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4496*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4497*1f6eb021SLiane Praza default: 4498*1f6eb021SLiane Praza return (NULL); 4499*1f6eb021SLiane Praza } 4500*1f6eb021SLiane Praza } 4501*1f6eb021SLiane Praza 4502*1f6eb021SLiane Praza static const char * 4503*1f6eb021SLiane Praza _get_ev1_desc(scf_tmpl_error_t *err) 4504*1f6eb021SLiane Praza { 4505*1f6eb021SLiane Praza switch (err->te_type) { 4506*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4507*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4508*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4509*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4510*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4511*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4512*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4513*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4514*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4515*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4516*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4517*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev1)); 4518*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4519*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4520*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4521*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4522*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4523*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4524*1f6eb021SLiane Praza default: 4525*1f6eb021SLiane Praza return (NULL); 4526*1f6eb021SLiane Praza } 4527*1f6eb021SLiane Praza } 4528*1f6eb021SLiane Praza 4529*1f6eb021SLiane Praza static const char * 4530*1f6eb021SLiane Praza _get_ev2_desc(scf_tmpl_error_t *err) 4531*1f6eb021SLiane Praza { 4532*1f6eb021SLiane Praza switch (err->te_type) { 4533*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4534*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4535*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4536*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4537*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4538*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4539*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4540*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_desc[err->te_type].em_ev2)); 4541*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4542*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4543*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4544*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4545*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4546*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4547*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4548*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4549*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4550*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4551*1f6eb021SLiane Praza default: 4552*1f6eb021SLiane Praza return (NULL); 4553*1f6eb021SLiane Praza } 4554*1f6eb021SLiane Praza } 4555*1f6eb021SLiane Praza 4556*1f6eb021SLiane Praza static const char * 4557*1f6eb021SLiane Praza _get_actual_desc(scf_tmpl_error_t *err) 4558*1f6eb021SLiane Praza { 4559*1f6eb021SLiane Praza switch (err->te_type) { 4560*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4561*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4562*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4563*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4564*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4565*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4566*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4567*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4568*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4569*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4570*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4571*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4572*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4573*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, 4574*1f6eb021SLiane Praza em_desc[err->te_type].em_actual)); 4575*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4576*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4577*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4578*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4579*1f6eb021SLiane Praza default: 4580*1f6eb021SLiane Praza return (NULL); 4581*1f6eb021SLiane Praza } 4582*1f6eb021SLiane Praza } 4583*1f6eb021SLiane Praza 4584*1f6eb021SLiane Praza static const char * 4585*1f6eb021SLiane Praza _get_tmpl_fmri_desc(scf_tmpl_error_t *err) 4586*1f6eb021SLiane Praza { 4587*1f6eb021SLiane Praza switch (err->te_type) { 4588*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4589*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4590*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4591*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4592*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4593*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4594*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4595*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4596*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4597*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4598*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4599*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4600*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4601*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4602*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4603*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4604*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4605*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_fmri)); 4606*1f6eb021SLiane Praza default: 4607*1f6eb021SLiane Praza return (NULL); 4608*1f6eb021SLiane Praza } 4609*1f6eb021SLiane Praza } 4610*1f6eb021SLiane Praza 4611*1f6eb021SLiane Praza static const char * 4612*1f6eb021SLiane Praza _get_tmpl_pg_name_desc(scf_tmpl_error_t *err) 4613*1f6eb021SLiane Praza { 4614*1f6eb021SLiane Praza switch (err->te_type) { 4615*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4616*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4617*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4618*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4619*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4620*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4621*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4622*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4623*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4624*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4625*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4626*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4627*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4628*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4629*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4630*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4631*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4632*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_pg_name)); 4633*1f6eb021SLiane Praza default: 4634*1f6eb021SLiane Praza return (NULL); 4635*1f6eb021SLiane Praza } 4636*1f6eb021SLiane Praza } 4637*1f6eb021SLiane Praza 4638*1f6eb021SLiane Praza static const char * 4639*1f6eb021SLiane Praza _get_tmpl_pg_type_desc(scf_tmpl_error_t *err) 4640*1f6eb021SLiane Praza { 4641*1f6eb021SLiane Praza switch (err->te_type) { 4642*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4643*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4644*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4645*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4646*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4647*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4648*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4649*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4650*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4651*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4652*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4653*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4654*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4655*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4656*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4657*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4658*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4659*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_pg_type)); 4660*1f6eb021SLiane Praza default: 4661*1f6eb021SLiane Praza return (NULL); 4662*1f6eb021SLiane Praza } 4663*1f6eb021SLiane Praza } 4664*1f6eb021SLiane Praza 4665*1f6eb021SLiane Praza static const char * 4666*1f6eb021SLiane Praza _get_tmpl_prop_name_desc(scf_tmpl_error_t *err) 4667*1f6eb021SLiane Praza { 4668*1f6eb021SLiane Praza switch (err->te_type) { 4669*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4670*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4671*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4672*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4673*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4674*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4675*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4676*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4677*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4678*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4679*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4680*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_prop_name)); 4681*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4682*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4683*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4684*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4685*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4686*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4687*1f6eb021SLiane Praza default: 4688*1f6eb021SLiane Praza return (NULL); 4689*1f6eb021SLiane Praza } 4690*1f6eb021SLiane Praza } 4691*1f6eb021SLiane Praza 4692*1f6eb021SLiane Praza static const char * 4693*1f6eb021SLiane Praza _get_tmpl_prop_type_desc(scf_tmpl_error_t *err) 4694*1f6eb021SLiane Praza { 4695*1f6eb021SLiane Praza switch (err->te_type) { 4696*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 4697*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 4698*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 4699*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 4700*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 4701*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 4702*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 4703*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 4704*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_CONFLICT: 4705*1f6eb021SLiane Praza case SCF_TERR_INCLUDE_VALUES: 4706*1f6eb021SLiane Praza return (dgettext(TEXT_DOMAIN, em_tmpl_prop_type)); 4707*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 4708*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 4709*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 4710*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_CONFLICT: 4711*1f6eb021SLiane Praza case SCF_TERR_GENERAL_REDEFINE: 4712*1f6eb021SLiane Praza case SCF_TERR_PG_PATTERN_INCOMPLETE: 4713*1f6eb021SLiane Praza case SCF_TERR_PROP_PATTERN_INCOMPLETE: 4714*1f6eb021SLiane Praza default: 4715*1f6eb021SLiane Praza return (NULL); 4716*1f6eb021SLiane Praza } 4717*1f6eb021SLiane Praza } 4718*1f6eb021SLiane Praza 4719*1f6eb021SLiane Praza static const char * 4720*1f6eb021SLiane Praza _get_fmri_val(scf_tmpl_error_t *err) 4721*1f6eb021SLiane Praza { 4722*1f6eb021SLiane Praza assert(err != NULL && err->te_errs != NULL && 4723*1f6eb021SLiane Praza err->te_errs->tes_fmri != NULL); 4724*1f6eb021SLiane Praza return (err->te_errs->tes_fmri); 4725*1f6eb021SLiane Praza } 4726*1f6eb021SLiane Praza 4727*1f6eb021SLiane Praza static const char * 4728*1f6eb021SLiane Praza _get_pg_name_val(scf_tmpl_error_t *err) 4729*1f6eb021SLiane Praza { 4730*1f6eb021SLiane Praza assert(err != NULL); 4731*1f6eb021SLiane Praza return (err->te_pg_name); 4732*1f6eb021SLiane Praza } 4733*1f6eb021SLiane Praza 4734*1f6eb021SLiane Praza static const char * 4735*1f6eb021SLiane Praza _get_prop_name_val(scf_tmpl_error_t *err) 4736*1f6eb021SLiane Praza { 4737*1f6eb021SLiane Praza assert(err != NULL); 4738*1f6eb021SLiane Praza return (err->te_prop_name); 4739*1f6eb021SLiane Praza } 4740*1f6eb021SLiane Praza 4741*1f6eb021SLiane Praza static const char * 4742*1f6eb021SLiane Praza _get_ev1_val(scf_tmpl_error_t *err) 4743*1f6eb021SLiane Praza { 4744*1f6eb021SLiane Praza assert(err != NULL); 4745*1f6eb021SLiane Praza return (err->te_ev1); 4746*1f6eb021SLiane Praza } 4747*1f6eb021SLiane Praza 4748*1f6eb021SLiane Praza static const char * 4749*1f6eb021SLiane Praza _get_ev2_val(scf_tmpl_error_t *err) 4750*1f6eb021SLiane Praza { 4751*1f6eb021SLiane Praza assert(err != NULL); 4752*1f6eb021SLiane Praza return (err->te_ev2); 4753*1f6eb021SLiane Praza } 4754*1f6eb021SLiane Praza 4755*1f6eb021SLiane Praza static const char * 4756*1f6eb021SLiane Praza _get_actual_val(scf_tmpl_error_t *err) 4757*1f6eb021SLiane Praza { 4758*1f6eb021SLiane Praza assert(err != NULL); 4759*1f6eb021SLiane Praza return (err->te_actual); 4760*1f6eb021SLiane Praza } 4761*1f6eb021SLiane Praza 4762*1f6eb021SLiane Praza static const char * 4763*1f6eb021SLiane Praza _get_tmpl_fmri_val(scf_tmpl_error_t *err) 4764*1f6eb021SLiane Praza { 4765*1f6eb021SLiane Praza assert(err != NULL); 4766*1f6eb021SLiane Praza return (err->te_tmpl_fmri); 4767*1f6eb021SLiane Praza } 4768*1f6eb021SLiane Praza 4769*1f6eb021SLiane Praza static const char * 4770*1f6eb021SLiane Praza _get_tmpl_pg_name_val(scf_tmpl_error_t *err) 4771*1f6eb021SLiane Praza { 4772*1f6eb021SLiane Praza assert(err != NULL); 4773*1f6eb021SLiane Praza return (err->te_tmpl_pg_name); 4774*1f6eb021SLiane Praza } 4775*1f6eb021SLiane Praza 4776*1f6eb021SLiane Praza static const char * 4777*1f6eb021SLiane Praza _get_tmpl_pg_type_val(scf_tmpl_error_t *err) 4778*1f6eb021SLiane Praza { 4779*1f6eb021SLiane Praza assert(err != NULL); 4780*1f6eb021SLiane Praza return (err->te_tmpl_pg_type); 4781*1f6eb021SLiane Praza } 4782*1f6eb021SLiane Praza 4783*1f6eb021SLiane Praza static const char * 4784*1f6eb021SLiane Praza _get_tmpl_prop_name_val(scf_tmpl_error_t *err) 4785*1f6eb021SLiane Praza { 4786*1f6eb021SLiane Praza assert(err != NULL); 4787*1f6eb021SLiane Praza return (err->te_tmpl_prop_name); 4788*1f6eb021SLiane Praza } 4789*1f6eb021SLiane Praza 4790*1f6eb021SLiane Praza static const char * 4791*1f6eb021SLiane Praza _get_tmpl_prop_type_val(scf_tmpl_error_t *err) 4792*1f6eb021SLiane Praza { 4793*1f6eb021SLiane Praza assert(err != NULL); 4794*1f6eb021SLiane Praza return (err->te_tmpl_prop_type); 4795*1f6eb021SLiane Praza } 4796*1f6eb021SLiane Praza 4797*1f6eb021SLiane Praza /* 4798*1f6eb021SLiane Praza * Templates error item retrival functions 4799*1f6eb021SLiane Praza */ 4800*1f6eb021SLiane Praza typedef const char *(*get_em)(scf_tmpl_error_t *); 4801*1f6eb021SLiane Praza 4802*1f6eb021SLiane Praza /* 4803*1f6eb021SLiane Praza * if new items (lines) are added to the templates error messages, 4804*1f6eb021SLiane Praza * new entries in this array (and new fuctions) will be required. 4805*1f6eb021SLiane Praza */ 4806*1f6eb021SLiane Praza static struct _tmpl_error_access { 4807*1f6eb021SLiane Praza get_em get_desc; 4808*1f6eb021SLiane Praza get_em get_val; 4809*1f6eb021SLiane Praza } _tmpl_error_items[] = { 4810*1f6eb021SLiane Praza { (get_em)_get_fmri_desc, (get_em)_get_fmri_val }, 4811*1f6eb021SLiane Praza { (get_em)_get_pg_name_desc, (get_em)_get_pg_name_val }, 4812*1f6eb021SLiane Praza { (get_em)_get_prop_name_desc, (get_em)_get_prop_name_val }, 4813*1f6eb021SLiane Praza { (get_em)_get_ev1_desc, (get_em)_get_ev1_val }, 4814*1f6eb021SLiane Praza { (get_em)_get_ev2_desc, (get_em)_get_ev2_val }, 4815*1f6eb021SLiane Praza { (get_em)_get_actual_desc, (get_em)_get_actual_val }, 4816*1f6eb021SLiane Praza { (get_em)_get_tmpl_fmri_desc, (get_em)_get_tmpl_fmri_val }, 4817*1f6eb021SLiane Praza { (get_em)_get_tmpl_pg_name_desc, (get_em)_get_tmpl_pg_name_val }, 4818*1f6eb021SLiane Praza { (get_em)_get_tmpl_pg_type_desc, (get_em)_get_tmpl_pg_type_val }, 4819*1f6eb021SLiane Praza { (get_em)_get_tmpl_prop_name_desc, (get_em)_get_tmpl_prop_name_val }, 4820*1f6eb021SLiane Praza { (get_em)_get_tmpl_prop_type_desc, (get_em)_get_tmpl_prop_type_val }, 4821*1f6eb021SLiane Praza { NULL } 4822*1f6eb021SLiane Praza }; 4823*1f6eb021SLiane Praza 4824*1f6eb021SLiane Praza /* 4825*1f6eb021SLiane Praza * Allocate a new scf_tmpl_error_t and add it to the errs list provided. 4826*1f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 4827*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4828*1f6eb021SLiane Praza */ 4829*1f6eb021SLiane Praza static scf_tmpl_error_t * 4830*1f6eb021SLiane Praza _create_error(scf_tmpl_errors_t *errs) 4831*1f6eb021SLiane Praza { 4832*1f6eb021SLiane Praza scf_tmpl_error_t *ret; 4833*1f6eb021SLiane Praza scf_tmpl_error_t **saved_errs; 4834*1f6eb021SLiane Praza 4835*1f6eb021SLiane Praza assert(errs != NULL); 4836*1f6eb021SLiane Praza ret = calloc(1, sizeof (scf_tmpl_error_t)); 4837*1f6eb021SLiane Praza if (ret == NULL) { 4838*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4839*1f6eb021SLiane Praza return (NULL); 4840*1f6eb021SLiane Praza } 4841*1f6eb021SLiane Praza 4842*1f6eb021SLiane Praza ret->te_errs = errs; 4843*1f6eb021SLiane Praza 4844*1f6eb021SLiane Praza assert(errs->tes_num_errs <= errs->tes_errs_size); 4845*1f6eb021SLiane Praza if (errs->tes_num_errs == errs->tes_errs_size) { 4846*1f6eb021SLiane Praza /* Time to grow the pointer array. */ 4847*1f6eb021SLiane Praza saved_errs = errs->tes_errs; 4848*1f6eb021SLiane Praza errs->tes_errs = calloc(2 * errs->tes_errs_size, 4849*1f6eb021SLiane Praza sizeof (scf_tmpl_error_t *)); 4850*1f6eb021SLiane Praza if (errs->tes_errs == NULL) { 4851*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4852*1f6eb021SLiane Praza errs->tes_errs = saved_errs; 4853*1f6eb021SLiane Praza free(ret); 4854*1f6eb021SLiane Praza return (NULL); 4855*1f6eb021SLiane Praza } 4856*1f6eb021SLiane Praza (void) memcpy(errs->tes_errs, saved_errs, errs->tes_errs_size * 4857*1f6eb021SLiane Praza sizeof (scf_tmpl_error_t *)); 4858*1f6eb021SLiane Praza errs->tes_errs_size = 2 * errs->tes_errs_size; 4859*1f6eb021SLiane Praza free(saved_errs); 4860*1f6eb021SLiane Praza } 4861*1f6eb021SLiane Praza 4862*1f6eb021SLiane Praza errs->tes_errs[errs->tes_num_errs] = ret; 4863*1f6eb021SLiane Praza errs->tes_num_errs++; 4864*1f6eb021SLiane Praza 4865*1f6eb021SLiane Praza return (ret); 4866*1f6eb021SLiane Praza } 4867*1f6eb021SLiane Praza 4868*1f6eb021SLiane Praza /* 4869*1f6eb021SLiane Praza * 4870*1f6eb021SLiane Praza * If destroy_strings is set, scf_tmpl_errors_destroy will free the 4871*1f6eb021SLiane Praza * strings in scf_tmpl_error_t entries. 4872*1f6eb021SLiane Praza * 4873*1f6eb021SLiane Praza * Returns NULL on failure. Sets scf_error(): 4874*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4875*1f6eb021SLiane Praza */ 4876*1f6eb021SLiane Praza scf_tmpl_errors_t * 4877*1f6eb021SLiane Praza _scf_create_errors(const char *fmri, int destroy_strings) 4878*1f6eb021SLiane Praza { 4879*1f6eb021SLiane Praza scf_tmpl_errors_t *ret; 4880*1f6eb021SLiane Praza int errs_size = 20; 4881*1f6eb021SLiane Praza 4882*1f6eb021SLiane Praza assert(fmri != NULL); 4883*1f6eb021SLiane Praza 4884*1f6eb021SLiane Praza ret = calloc(1, sizeof (scf_tmpl_errors_t)); 4885*1f6eb021SLiane Praza if (ret == NULL) { 4886*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4887*1f6eb021SLiane Praza return (NULL); 4888*1f6eb021SLiane Praza } 4889*1f6eb021SLiane Praza 4890*1f6eb021SLiane Praza ret->tes_index = 0; 4891*1f6eb021SLiane Praza ret->tes_num_errs = 0; 4892*1f6eb021SLiane Praza if ((ret->tes_fmri = strdup(fmri)) == NULL) { 4893*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4894*1f6eb021SLiane Praza free(ret); 4895*1f6eb021SLiane Praza return (NULL); 4896*1f6eb021SLiane Praza } 4897*1f6eb021SLiane Praza 4898*1f6eb021SLiane Praza ret->tes_prefix = strdup(""); 4899*1f6eb021SLiane Praza if (ret->tes_prefix == NULL) { 4900*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4901*1f6eb021SLiane Praza free((char *)ret->tes_fmri); 4902*1f6eb021SLiane Praza free(ret); 4903*1f6eb021SLiane Praza return (NULL); 4904*1f6eb021SLiane Praza } 4905*1f6eb021SLiane Praza ret->tes_flag = destroy_strings; 4906*1f6eb021SLiane Praza 4907*1f6eb021SLiane Praza /* Make space for a few errors. */ 4908*1f6eb021SLiane Praza ret->tes_errs = calloc(errs_size, sizeof (scf_tmpl_error_t *)); 4909*1f6eb021SLiane Praza if (ret->tes_errs == NULL) { 4910*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4911*1f6eb021SLiane Praza free((char *)ret->tes_fmri); 4912*1f6eb021SLiane Praza free((char *)ret->tes_prefix); 4913*1f6eb021SLiane Praza free(ret); 4914*1f6eb021SLiane Praza return (NULL); 4915*1f6eb021SLiane Praza } 4916*1f6eb021SLiane Praza ret->tes_errs_size = errs_size; 4917*1f6eb021SLiane Praza 4918*1f6eb021SLiane Praza return (ret); 4919*1f6eb021SLiane Praza } 4920*1f6eb021SLiane Praza 4921*1f6eb021SLiane Praza /* 4922*1f6eb021SLiane Praza * return 0 on success, if fails set scf_error() to: 4923*1f6eb021SLiane Praza * 4924*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4925*1f6eb021SLiane Praza */ 4926*1f6eb021SLiane Praza int 4927*1f6eb021SLiane Praza _scf_tmpl_error_set_prefix(scf_tmpl_errors_t *errs, const char *prefix) 4928*1f6eb021SLiane Praza { 4929*1f6eb021SLiane Praza free((void *) errs->tes_prefix); 4930*1f6eb021SLiane Praza if (prefix == NULL) 4931*1f6eb021SLiane Praza errs->tes_prefix = strdup(""); 4932*1f6eb021SLiane Praza else 4933*1f6eb021SLiane Praza errs->tes_prefix = strdup(prefix); 4934*1f6eb021SLiane Praza if (errs->tes_prefix == NULL) { 4935*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4936*1f6eb021SLiane Praza return (-1); 4937*1f6eb021SLiane Praza } 4938*1f6eb021SLiane Praza return (0); 4939*1f6eb021SLiane Praza } 4940*1f6eb021SLiane Praza 4941*1f6eb021SLiane Praza /* 4942*1f6eb021SLiane Praza * 4943*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 4944*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4945*1f6eb021SLiane Praza */ 4946*1f6eb021SLiane Praza int 4947*1f6eb021SLiane Praza _scf_tmpl_add_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 4948*1f6eb021SLiane Praza const char *pg_name, const char *prop_name, 4949*1f6eb021SLiane Praza const char *ev1, const char *ev2, const char *actual, 4950*1f6eb021SLiane Praza const char *tmpl_fmri, const char *tmpl_pg_name, const char *tmpl_pg_type, 4951*1f6eb021SLiane Praza const char *tmpl_prop_name, const char *tmpl_prop_type) 4952*1f6eb021SLiane Praza { 4953*1f6eb021SLiane Praza scf_tmpl_error_t *err; 4954*1f6eb021SLiane Praza 4955*1f6eb021SLiane Praza assert(errs != NULL); 4956*1f6eb021SLiane Praza assert(tmpl_fmri != NULL); 4957*1f6eb021SLiane Praza 4958*1f6eb021SLiane Praza err = _create_error(errs); 4959*1f6eb021SLiane Praza if (err == NULL) 4960*1f6eb021SLiane Praza return (-1); 4961*1f6eb021SLiane Praza 4962*1f6eb021SLiane Praza err->te_type = type; 4963*1f6eb021SLiane Praza err->te_pg_name = pg_name; 4964*1f6eb021SLiane Praza err->te_prop_name = prop_name; 4965*1f6eb021SLiane Praza err->te_ev1 = ev1; 4966*1f6eb021SLiane Praza err->te_ev2 = ev2; 4967*1f6eb021SLiane Praza err->te_actual = actual; 4968*1f6eb021SLiane Praza err->te_tmpl_fmri = tmpl_fmri; 4969*1f6eb021SLiane Praza err->te_tmpl_pg_name = tmpl_pg_name; 4970*1f6eb021SLiane Praza err->te_tmpl_pg_type = tmpl_pg_type; 4971*1f6eb021SLiane Praza err->te_tmpl_prop_name = tmpl_prop_name; 4972*1f6eb021SLiane Praza err->te_tmpl_prop_type = tmpl_prop_type; 4973*1f6eb021SLiane Praza 4974*1f6eb021SLiane Praza return (0); 4975*1f6eb021SLiane Praza } 4976*1f6eb021SLiane Praza 4977*1f6eb021SLiane Praza /* 4978*1f6eb021SLiane Praza * returns an allocated string that must be freed with free() 4979*1f6eb021SLiane Praza * string contains converted 64-bit integer value 4980*1f6eb021SLiane Praza * flag set for signed values 4981*1f6eb021SLiane Praza * if fails return NULL and set scf_error() to: 4982*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 4983*1f6eb021SLiane Praza */ 4984*1f6eb021SLiane Praza static char * 4985*1f6eb021SLiane Praza _val_to_string(uint64_t val, int flag) 4986*1f6eb021SLiane Praza { 4987*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 4988*1f6eb021SLiane Praza char *buf; 4989*1f6eb021SLiane Praza 4990*1f6eb021SLiane Praza buf = malloc(sz); 4991*1f6eb021SLiane Praza if (buf == NULL) { 4992*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 4993*1f6eb021SLiane Praza return (NULL); 4994*1f6eb021SLiane Praza } 4995*1f6eb021SLiane Praza 4996*1f6eb021SLiane Praza if (flag == 0) 4997*1f6eb021SLiane Praza (void) snprintf(buf, sz, "%" PRIu64, val); 4998*1f6eb021SLiane Praza else 4999*1f6eb021SLiane Praza (void) snprintf(buf, sz, "%" PRIi64, (int64_t)val); 5000*1f6eb021SLiane Praza 5001*1f6eb021SLiane Praza return (buf); 5002*1f6eb021SLiane Praza } 5003*1f6eb021SLiane Praza 5004*1f6eb021SLiane Praza /* 5005*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5006*1f6eb021SLiane Praza * set scf_error() to: 5007*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5008*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5009*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5010*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5011*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5012*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5013*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5014*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5015*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5016*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5017*1f6eb021SLiane Praza */ 5018*1f6eb021SLiane Praza static int 5019*1f6eb021SLiane Praza _add_tmpl_missing_pg_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t) 5020*1f6eb021SLiane Praza { 5021*1f6eb021SLiane Praza char *ev1 = NULL; 5022*1f6eb021SLiane Praza char *ev2 = NULL; 5023*1f6eb021SLiane Praza char *t_fmri = NULL; 5024*1f6eb021SLiane Praza char *t_pg_name = NULL; 5025*1f6eb021SLiane Praza char *t_pg_type = NULL; 5026*1f6eb021SLiane Praza 5027*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL) 5028*1f6eb021SLiane Praza return (-1); 5029*1f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &t_pg_name) == -1) { 5030*1f6eb021SLiane Praza goto cleanup; 5031*1f6eb021SLiane Praza } 5032*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &t_pg_type) == -1) { 5033*1f6eb021SLiane Praza goto cleanup; 5034*1f6eb021SLiane Praza } 5035*1f6eb021SLiane Praza if ((ev1 = strdup(t_pg_name)) == NULL) { 5036*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5037*1f6eb021SLiane Praza goto cleanup; 5038*1f6eb021SLiane Praza } 5039*1f6eb021SLiane Praza if ((ev2 = strdup(t_pg_type)) == NULL) { 5040*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5041*1f6eb021SLiane Praza goto cleanup; 5042*1f6eb021SLiane Praza } 5043*1f6eb021SLiane Praza 5044*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PG, NULL, NULL, ev1, 5045*1f6eb021SLiane Praza ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL)); 5046*1f6eb021SLiane Praza cleanup: 5047*1f6eb021SLiane Praza free(ev1); 5048*1f6eb021SLiane Praza free(ev2); 5049*1f6eb021SLiane Praza free(t_fmri); 5050*1f6eb021SLiane Praza free(t_pg_name); 5051*1f6eb021SLiane Praza free(t_pg_type); 5052*1f6eb021SLiane Praza return (-1); 5053*1f6eb021SLiane Praza } 5054*1f6eb021SLiane Praza 5055*1f6eb021SLiane Praza /* 5056*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5057*1f6eb021SLiane Praza * set scf_error() to: 5058*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5059*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5060*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5061*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5062*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5063*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5064*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5065*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5066*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5067*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5068*1f6eb021SLiane Praza */ 5069*1f6eb021SLiane Praza static int 5070*1f6eb021SLiane Praza _add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t, 5071*1f6eb021SLiane Praza scf_propertygroup_t *pg) 5072*1f6eb021SLiane Praza { 5073*1f6eb021SLiane Praza char *pg_name = NULL; 5074*1f6eb021SLiane Praza char *ev1 = NULL; 5075*1f6eb021SLiane Praza char *actual = NULL; 5076*1f6eb021SLiane Praza char *t_fmri = NULL; 5077*1f6eb021SLiane Praza char *t_pg_name = NULL; 5078*1f6eb021SLiane Praza char *t_pg_type = NULL; 5079*1f6eb021SLiane Praza 5080*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL) 5081*1f6eb021SLiane Praza return (-1); 5082*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 5083*1f6eb021SLiane Praza goto cleanup; 5084*1f6eb021SLiane Praza if ((actual = _scf_get_pg_type(pg)) == NULL) 5085*1f6eb021SLiane Praza goto cleanup; 5086*1f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &t_pg_name) == -1) { 5087*1f6eb021SLiane Praza goto cleanup; 5088*1f6eb021SLiane Praza } 5089*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &t_pg_type) == -1) { 5090*1f6eb021SLiane Praza goto cleanup; 5091*1f6eb021SLiane Praza } 5092*1f6eb021SLiane Praza if ((ev1 = strdup(t_pg_type)) == NULL) { 5093*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5094*1f6eb021SLiane Praza goto cleanup; 5095*1f6eb021SLiane Praza } 5096*1f6eb021SLiane Praza 5097*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PG_TYPE, pg_name, NULL, 5098*1f6eb021SLiane Praza ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type, NULL, NULL)); 5099*1f6eb021SLiane Praza cleanup: 5100*1f6eb021SLiane Praza free(pg_name); 5101*1f6eb021SLiane Praza free(ev1); 5102*1f6eb021SLiane Praza free(actual); 5103*1f6eb021SLiane Praza free(t_fmri); 5104*1f6eb021SLiane Praza free(t_pg_name); 5105*1f6eb021SLiane Praza free(t_pg_type); 5106*1f6eb021SLiane Praza return (-1); 5107*1f6eb021SLiane Praza } 5108*1f6eb021SLiane Praza 5109*1f6eb021SLiane Praza /* 5110*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5111*1f6eb021SLiane Praza * set scf_error() to: 5112*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5113*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5114*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5115*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5116*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5117*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5118*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5119*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5120*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5121*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5122*1f6eb021SLiane Praza */ 5123*1f6eb021SLiane Praza static int 5124*1f6eb021SLiane Praza _add_tmpl_missing_prop_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t, 5125*1f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt) 5126*1f6eb021SLiane Praza { 5127*1f6eb021SLiane Praza char *pg_name = NULL; 5128*1f6eb021SLiane Praza char *ev1 = NULL; 5129*1f6eb021SLiane Praza char *t_fmri = NULL; 5130*1f6eb021SLiane Praza char *t_pg_name = NULL; 5131*1f6eb021SLiane Praza char *t_pg_type = NULL; 5132*1f6eb021SLiane Praza char *t_prop_name = NULL; 5133*1f6eb021SLiane Praza char *t_prop_type = NULL; 5134*1f6eb021SLiane Praza 5135*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(t)) == NULL) 5136*1f6eb021SLiane Praza return (-1); 5137*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 5138*1f6eb021SLiane Praza goto cleanup; 5139*1f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &t_pg_name) == -1) { 5140*1f6eb021SLiane Praza goto cleanup; 5141*1f6eb021SLiane Praza } 5142*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &t_pg_type) == -1) { 5143*1f6eb021SLiane Praza goto cleanup; 5144*1f6eb021SLiane Praza } 5145*1f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 5146*1f6eb021SLiane Praza goto cleanup; 5147*1f6eb021SLiane Praza } 5148*1f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 5149*1f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 5150*1f6eb021SLiane Praza free(t_prop_type); 5151*1f6eb021SLiane Praza t_prop_type = NULL; 5152*1f6eb021SLiane Praza } else if (t_prop_type == NULL) { 5153*1f6eb021SLiane Praza goto cleanup; 5154*1f6eb021SLiane Praza } 5155*1f6eb021SLiane Praza if (t_prop_type == NULL) 5156*1f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 5157*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5158*1f6eb021SLiane Praza goto cleanup; 5159*1f6eb021SLiane Praza } 5160*1f6eb021SLiane Praza if ((ev1 = strdup(t_prop_name)) == NULL) { 5161*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5162*1f6eb021SLiane Praza goto cleanup; 5163*1f6eb021SLiane Praza } 5164*1f6eb021SLiane Praza 5165*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_MISSING_PROP, pg_name, NULL, 5166*1f6eb021SLiane Praza ev1, NULL, NULL, t_fmri, t_pg_name, t_pg_type, t_prop_name, 5167*1f6eb021SLiane Praza t_prop_type)); 5168*1f6eb021SLiane Praza cleanup: 5169*1f6eb021SLiane Praza free(pg_name); 5170*1f6eb021SLiane Praza free(ev1); 5171*1f6eb021SLiane Praza free(t_fmri); 5172*1f6eb021SLiane Praza free(t_pg_name); 5173*1f6eb021SLiane Praza free(t_pg_type); 5174*1f6eb021SLiane Praza free(t_prop_name); 5175*1f6eb021SLiane Praza free(t_prop_type); 5176*1f6eb021SLiane Praza return (-1); 5177*1f6eb021SLiane Praza } 5178*1f6eb021SLiane Praza 5179*1f6eb021SLiane Praza /* 5180*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5181*1f6eb021SLiane Praza * set scf_error() to: 5182*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5183*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5184*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5185*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5186*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5187*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5188*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5189*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5190*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5191*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5192*1f6eb021SLiane Praza */ 5193*1f6eb021SLiane Praza static int 5194*1f6eb021SLiane Praza _add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t *errs, 5195*1f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop) 5196*1f6eb021SLiane Praza { 5197*1f6eb021SLiane Praza char *pg_name = NULL; 5198*1f6eb021SLiane Praza char *prop_name = NULL; 5199*1f6eb021SLiane Praza char *ev1 = NULL; 5200*1f6eb021SLiane Praza char *actual = NULL; 5201*1f6eb021SLiane Praza char *t_fmri = NULL; 5202*1f6eb021SLiane Praza char *t_pg_name = NULL; 5203*1f6eb021SLiane Praza char *t_pg_type = NULL; 5204*1f6eb021SLiane Praza char *t_prop_name = NULL; 5205*1f6eb021SLiane Praza char *t_prop_type = NULL; 5206*1f6eb021SLiane Praza 5207*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 5208*1f6eb021SLiane Praza return (-1); 5209*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 5210*1f6eb021SLiane Praza goto cleanup; 5211*1f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 5212*1f6eb021SLiane Praza goto cleanup; 5213*1f6eb021SLiane Praza if ((actual = _scf_get_prop_type(prop)) == NULL) 5214*1f6eb021SLiane Praza goto cleanup; 5215*1f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 5216*1f6eb021SLiane Praza goto cleanup; 5217*1f6eb021SLiane Praza } 5218*1f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 5219*1f6eb021SLiane Praza goto cleanup; 5220*1f6eb021SLiane Praza } 5221*1f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 5222*1f6eb021SLiane Praza goto cleanup; 5223*1f6eb021SLiane Praza } 5224*1f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 5225*1f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 5226*1f6eb021SLiane Praza free(t_prop_type); 5227*1f6eb021SLiane Praza t_prop_type = NULL; 5228*1f6eb021SLiane Praza } else if (t_prop_type == NULL) { 5229*1f6eb021SLiane Praza goto cleanup; 5230*1f6eb021SLiane Praza } 5231*1f6eb021SLiane Praza if (t_prop_type == NULL) 5232*1f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 5233*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5234*1f6eb021SLiane Praza goto cleanup; 5235*1f6eb021SLiane Praza } 5236*1f6eb021SLiane Praza if ((ev1 = strdup(t_prop_type)) == NULL) { 5237*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5238*1f6eb021SLiane Praza goto cleanup; 5239*1f6eb021SLiane Praza } 5240*1f6eb021SLiane Praza 5241*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_WRONG_PROP_TYPE, pg_name, 5242*1f6eb021SLiane Praza prop_name, ev1, NULL, actual, t_fmri, t_pg_name, t_pg_type, 5243*1f6eb021SLiane Praza t_prop_name, t_prop_type)); 5244*1f6eb021SLiane Praza cleanup: 5245*1f6eb021SLiane Praza free(pg_name); 5246*1f6eb021SLiane Praza free(prop_name); 5247*1f6eb021SLiane Praza free(ev1); 5248*1f6eb021SLiane Praza free(actual); 5249*1f6eb021SLiane Praza free(t_fmri); 5250*1f6eb021SLiane Praza free(t_pg_name); 5251*1f6eb021SLiane Praza free(t_pg_type); 5252*1f6eb021SLiane Praza free(t_prop_name); 5253*1f6eb021SLiane Praza free(t_prop_type); 5254*1f6eb021SLiane Praza return (-1); 5255*1f6eb021SLiane Praza } 5256*1f6eb021SLiane Praza 5257*1f6eb021SLiane Praza /* 5258*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5259*1f6eb021SLiane Praza * set scf_error() to: 5260*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5261*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5262*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5263*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5264*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5265*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5266*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5267*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5268*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5269*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5270*1f6eb021SLiane Praza */ 5271*1f6eb021SLiane Praza static int 5272*1f6eb021SLiane Praza _add_tmpl_count_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 5273*1f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop, 5274*1f6eb021SLiane Praza uint64_t count, uint64_t *min, uint64_t *max) 5275*1f6eb021SLiane Praza { 5276*1f6eb021SLiane Praza char *pg_name = NULL; 5277*1f6eb021SLiane Praza char *prop_name = NULL; 5278*1f6eb021SLiane Praza char *s_min = NULL; 5279*1f6eb021SLiane Praza char *s_max = NULL; 5280*1f6eb021SLiane Praza char *num = NULL; 5281*1f6eb021SLiane Praza char *t_fmri = NULL; 5282*1f6eb021SLiane Praza char *t_pg_name = NULL; 5283*1f6eb021SLiane Praza char *t_pg_type = NULL; 5284*1f6eb021SLiane Praza char *t_prop_name = NULL; 5285*1f6eb021SLiane Praza char *t_prop_type = NULL; 5286*1f6eb021SLiane Praza 5287*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 5288*1f6eb021SLiane Praza return (-1); 5289*1f6eb021SLiane Praza switch (type) { 5290*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 5291*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 5292*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 5293*1f6eb021SLiane Praza goto cleanup; 5294*1f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 5295*1f6eb021SLiane Praza goto cleanup; 5296*1f6eb021SLiane Praza break; 5297*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 5298*1f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 5299*1f6eb021SLiane Praza break; 5300*1f6eb021SLiane Praza } 5301*1f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 5302*1f6eb021SLiane Praza goto cleanup; 5303*1f6eb021SLiane Praza } 5304*1f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 5305*1f6eb021SLiane Praza goto cleanup; 5306*1f6eb021SLiane Praza } 5307*1f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 5308*1f6eb021SLiane Praza goto cleanup; 5309*1f6eb021SLiane Praza } 5310*1f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 5311*1f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 5312*1f6eb021SLiane Praza free(t_prop_type); 5313*1f6eb021SLiane Praza t_prop_type = NULL; 5314*1f6eb021SLiane Praza } else if (t_prop_type == NULL) { 5315*1f6eb021SLiane Praza goto cleanup; 5316*1f6eb021SLiane Praza } 5317*1f6eb021SLiane Praza if (t_prop_type == NULL) 5318*1f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 5319*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5320*1f6eb021SLiane Praza goto cleanup; 5321*1f6eb021SLiane Praza } 5322*1f6eb021SLiane Praza if (min == NULL) { 5323*1f6eb021SLiane Praza if ((s_min = strdup("")) == NULL) { 5324*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5325*1f6eb021SLiane Praza goto cleanup; 5326*1f6eb021SLiane Praza } 5327*1f6eb021SLiane Praza } else { 5328*1f6eb021SLiane Praza if ((s_min = _val_to_string(*min, 0)) == NULL) { 5329*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5330*1f6eb021SLiane Praza goto cleanup; 5331*1f6eb021SLiane Praza } 5332*1f6eb021SLiane Praza } 5333*1f6eb021SLiane Praza if (max == NULL) { 5334*1f6eb021SLiane Praza if ((s_max = strdup("")) == NULL) { 5335*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5336*1f6eb021SLiane Praza goto cleanup; 5337*1f6eb021SLiane Praza } 5338*1f6eb021SLiane Praza } else { 5339*1f6eb021SLiane Praza if ((s_max = _val_to_string(*max, 0)) == NULL) { 5340*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5341*1f6eb021SLiane Praza goto cleanup; 5342*1f6eb021SLiane Praza } 5343*1f6eb021SLiane Praza } 5344*1f6eb021SLiane Praza if ((num = _val_to_string(count, 0)) == NULL) { 5345*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5346*1f6eb021SLiane Praza goto cleanup; 5347*1f6eb021SLiane Praza } 5348*1f6eb021SLiane Praza 5349*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min, 5350*1f6eb021SLiane Praza s_max, num, t_fmri, t_pg_name, t_pg_type, t_prop_name, 5351*1f6eb021SLiane Praza t_prop_type)); 5352*1f6eb021SLiane Praza cleanup: 5353*1f6eb021SLiane Praza free(pg_name); 5354*1f6eb021SLiane Praza free(prop_name); 5355*1f6eb021SLiane Praza free(s_min); 5356*1f6eb021SLiane Praza free(s_max); 5357*1f6eb021SLiane Praza free(num); 5358*1f6eb021SLiane Praza free(t_fmri); 5359*1f6eb021SLiane Praza free(t_pg_name); 5360*1f6eb021SLiane Praza free(t_pg_type); 5361*1f6eb021SLiane Praza free(t_prop_name); 5362*1f6eb021SLiane Praza free(t_prop_type); 5363*1f6eb021SLiane Praza return (-1); 5364*1f6eb021SLiane Praza } 5365*1f6eb021SLiane Praza 5366*1f6eb021SLiane Praza /* 5367*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5368*1f6eb021SLiane Praza * set scf_error() to: 5369*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5370*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5371*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5372*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5373*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5374*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5375*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5376*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5377*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5378*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5379*1f6eb021SLiane Praza */ 5380*1f6eb021SLiane Praza static int 5381*1f6eb021SLiane Praza _add_tmpl_constraint_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 5382*1f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop, 5383*1f6eb021SLiane Praza scf_value_t *val) 5384*1f6eb021SLiane Praza { 5385*1f6eb021SLiane Praza scf_type_t val_type; 5386*1f6eb021SLiane Praza char *pg_name = NULL; 5387*1f6eb021SLiane Praza char *prop_name = NULL; 5388*1f6eb021SLiane Praza char *value = NULL; 5389*1f6eb021SLiane Praza char *t_fmri = NULL; 5390*1f6eb021SLiane Praza char *t_pg_name = NULL; 5391*1f6eb021SLiane Praza char *t_pg_type = NULL; 5392*1f6eb021SLiane Praza char *t_prop_name = NULL; 5393*1f6eb021SLiane Praza char *t_prop_type = NULL; 5394*1f6eb021SLiane Praza 5395*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 5396*1f6eb021SLiane Praza return (-1); 5397*1f6eb021SLiane Praza switch (type) { 5398*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 5399*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 5400*1f6eb021SLiane Praza goto cleanup; 5401*1f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 5402*1f6eb021SLiane Praza goto cleanup; 5403*1f6eb021SLiane Praza /*FALLTHROUGH*/ 5404*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 5405*1f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 5406*1f6eb021SLiane Praza if ((value = _scf_value_get_as_string(val)) == NULL) 5407*1f6eb021SLiane Praza goto cleanup; 5408*1f6eb021SLiane Praza break; 5409*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 5410*1f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 5411*1f6eb021SLiane Praza /* use value for value type */ 5412*1f6eb021SLiane Praza val_type = scf_value_type(val); 5413*1f6eb021SLiane Praza if ((value = strdup(scf_type_to_string(val_type))) == 5414*1f6eb021SLiane Praza NULL) { 5415*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5416*1f6eb021SLiane Praza goto cleanup; 5417*1f6eb021SLiane Praza } 5418*1f6eb021SLiane Praza break; 5419*1f6eb021SLiane Praza } 5420*1f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 5421*1f6eb021SLiane Praza goto cleanup; 5422*1f6eb021SLiane Praza } 5423*1f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 5424*1f6eb021SLiane Praza goto cleanup; 5425*1f6eb021SLiane Praza } 5426*1f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 5427*1f6eb021SLiane Praza goto cleanup; 5428*1f6eb021SLiane Praza } 5429*1f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 5430*1f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 5431*1f6eb021SLiane Praza free(t_prop_type); 5432*1f6eb021SLiane Praza t_prop_type = NULL; 5433*1f6eb021SLiane Praza } else if (t_prop_type == NULL) { 5434*1f6eb021SLiane Praza goto cleanup; 5435*1f6eb021SLiane Praza } 5436*1f6eb021SLiane Praza if (t_prop_type == NULL) 5437*1f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 5438*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5439*1f6eb021SLiane Praza goto cleanup; 5440*1f6eb021SLiane Praza } 5441*1f6eb021SLiane Praza 5442*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, NULL, NULL, 5443*1f6eb021SLiane Praza value, t_fmri, t_pg_name, t_pg_type, t_prop_name, t_prop_type)); 5444*1f6eb021SLiane Praza cleanup: 5445*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 5446*1f6eb021SLiane Praza free(pg_name); 5447*1f6eb021SLiane Praza free(prop_name); 5448*1f6eb021SLiane Praza free(value); 5449*1f6eb021SLiane Praza free(t_fmri); 5450*1f6eb021SLiane Praza free(t_pg_name); 5451*1f6eb021SLiane Praza free(t_pg_type); 5452*1f6eb021SLiane Praza free(t_prop_name); 5453*1f6eb021SLiane Praza free(t_prop_type); 5454*1f6eb021SLiane Praza return (-1); 5455*1f6eb021SLiane Praza } 5456*1f6eb021SLiane Praza 5457*1f6eb021SLiane Praza /* 5458*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5459*1f6eb021SLiane Praza * set scf_error() to: 5460*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5461*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5462*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5463*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5464*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5465*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5466*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5467*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5468*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5469*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5470*1f6eb021SLiane Praza */ 5471*1f6eb021SLiane Praza static int 5472*1f6eb021SLiane Praza _add_tmpl_int_error(scf_tmpl_errors_t *errs, scf_tmpl_error_type_t type, 5473*1f6eb021SLiane Praza scf_propertygroup_t *pg, const scf_prop_tmpl_t *pt, scf_property_t *prop, 5474*1f6eb021SLiane Praza int64_t val, int64_t *min, int64_t *max) 5475*1f6eb021SLiane Praza { 5476*1f6eb021SLiane Praza char *pg_name = NULL; 5477*1f6eb021SLiane Praza char *prop_name = NULL; 5478*1f6eb021SLiane Praza char *s_min = NULL; 5479*1f6eb021SLiane Praza char *s_max = NULL; 5480*1f6eb021SLiane Praza char *value = NULL; 5481*1f6eb021SLiane Praza char *t_fmri = NULL; 5482*1f6eb021SLiane Praza char *t_pg_name = NULL; 5483*1f6eb021SLiane Praza char *t_pg_type = NULL; 5484*1f6eb021SLiane Praza char *t_prop_name = NULL; 5485*1f6eb021SLiane Praza char *t_prop_type = NULL; 5486*1f6eb021SLiane Praza 5487*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 5488*1f6eb021SLiane Praza return (-1); 5489*1f6eb021SLiane Praza 5490*1f6eb021SLiane Praza switch (type) { 5491*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 5492*1f6eb021SLiane Praza if ((pg_name = _scf_get_pg_name(pg)) == NULL) 5493*1f6eb021SLiane Praza goto cleanup; 5494*1f6eb021SLiane Praza if ((prop_name = _scf_get_prop_name(prop)) == NULL) 5495*1f6eb021SLiane Praza goto cleanup; 5496*1f6eb021SLiane Praza break; 5497*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 5498*1f6eb021SLiane Praza /* keep pg_name = NULL and prop_name = NULL */ 5499*1f6eb021SLiane Praza break; 5500*1f6eb021SLiane Praza } 5501*1f6eb021SLiane Praza if (scf_tmpl_pg_name(pt->prt_t, &t_pg_name) == -1) { 5502*1f6eb021SLiane Praza goto cleanup; 5503*1f6eb021SLiane Praza } 5504*1f6eb021SLiane Praza if (scf_tmpl_pg_type(pt->prt_t, &t_pg_type) == -1) { 5505*1f6eb021SLiane Praza goto cleanup; 5506*1f6eb021SLiane Praza } 5507*1f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &t_prop_name) == -1) { 5508*1f6eb021SLiane Praza goto cleanup; 5509*1f6eb021SLiane Praza } 5510*1f6eb021SLiane Praza t_prop_type = _scf_read_tmpl_prop_type_as_string(pt); 5511*1f6eb021SLiane Praza if (t_prop_type != NULL && t_prop_type[0] == '\0') { 5512*1f6eb021SLiane Praza free(t_prop_type); 5513*1f6eb021SLiane Praza t_prop_type = NULL; 5514*1f6eb021SLiane Praza } else if (t_prop_type == NULL) { 5515*1f6eb021SLiane Praza goto cleanup; 5516*1f6eb021SLiane Praza } 5517*1f6eb021SLiane Praza if (t_prop_type == NULL) 5518*1f6eb021SLiane Praza if ((t_prop_type = strdup(SCF_TMPL_WILDCARD)) == NULL) { 5519*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5520*1f6eb021SLiane Praza goto cleanup; 5521*1f6eb021SLiane Praza } 5522*1f6eb021SLiane Praza if (min == NULL) { 5523*1f6eb021SLiane Praza if ((s_min = strdup("")) == NULL) { 5524*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5525*1f6eb021SLiane Praza goto cleanup; 5526*1f6eb021SLiane Praza } 5527*1f6eb021SLiane Praza } else { 5528*1f6eb021SLiane Praza if ((s_min = _val_to_string(*((uint64_t *)min), 1)) == NULL) { 5529*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5530*1f6eb021SLiane Praza goto cleanup; 5531*1f6eb021SLiane Praza } 5532*1f6eb021SLiane Praza } 5533*1f6eb021SLiane Praza if (max == NULL) { 5534*1f6eb021SLiane Praza if ((s_max = strdup("")) == NULL) { 5535*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5536*1f6eb021SLiane Praza goto cleanup; 5537*1f6eb021SLiane Praza } 5538*1f6eb021SLiane Praza } else { 5539*1f6eb021SLiane Praza if ((s_max = _val_to_string(*((uint64_t *)max), 1)) == NULL) { 5540*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5541*1f6eb021SLiane Praza goto cleanup; 5542*1f6eb021SLiane Praza } 5543*1f6eb021SLiane Praza } 5544*1f6eb021SLiane Praza if ((value = _val_to_string((uint64_t)val, 1)) == NULL) { 5545*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5546*1f6eb021SLiane Praza goto cleanup; 5547*1f6eb021SLiane Praza } 5548*1f6eb021SLiane Praza 5549*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, type, pg_name, prop_name, s_min, 5550*1f6eb021SLiane Praza s_max, value, t_fmri, t_pg_name, t_pg_type, t_prop_name, 5551*1f6eb021SLiane Praza t_prop_type)); 5552*1f6eb021SLiane Praza cleanup: 5553*1f6eb021SLiane Praza free(pg_name); 5554*1f6eb021SLiane Praza free(prop_name); 5555*1f6eb021SLiane Praza free(s_min); 5556*1f6eb021SLiane Praza free(s_max); 5557*1f6eb021SLiane Praza free(value); 5558*1f6eb021SLiane Praza free(t_fmri); 5559*1f6eb021SLiane Praza free(t_pg_name); 5560*1f6eb021SLiane Praza free(t_pg_type); 5561*1f6eb021SLiane Praza free(t_prop_name); 5562*1f6eb021SLiane Praza free(t_prop_type); 5563*1f6eb021SLiane Praza return (-1); 5564*1f6eb021SLiane Praza } 5565*1f6eb021SLiane Praza 5566*1f6eb021SLiane Praza /* 5567*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5568*1f6eb021SLiane Praza * set scf_error() to: 5569*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5570*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5571*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5572*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5573*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5574*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5575*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5576*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5577*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5578*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5579*1f6eb021SLiane Praza */ 5580*1f6eb021SLiane Praza static int 5581*1f6eb021SLiane Praza _add_tmpl_pg_redefine_error(scf_tmpl_errors_t *errs, scf_pg_tmpl_t *t, 5582*1f6eb021SLiane Praza scf_pg_tmpl_t *r) 5583*1f6eb021SLiane Praza { 5584*1f6eb021SLiane Praza char *ev1 = NULL; 5585*1f6eb021SLiane Praza char *ev2 = NULL; 5586*1f6eb021SLiane Praza char *t_fmri = NULL; 5587*1f6eb021SLiane Praza char *t_pg_name = NULL; 5588*1f6eb021SLiane Praza char *t_pg_type = NULL; 5589*1f6eb021SLiane Praza 5590*1f6eb021SLiane Praza if ((t_fmri = _scf_tmpl_get_fmri(r)) == NULL) 5591*1f6eb021SLiane Praza return (-1); 5592*1f6eb021SLiane Praza if (scf_tmpl_pg_name(r, &t_pg_name) == -1) { 5593*1f6eb021SLiane Praza goto cleanup; 5594*1f6eb021SLiane Praza } 5595*1f6eb021SLiane Praza if (scf_tmpl_pg_type(r, &t_pg_type) == -1) { 5596*1f6eb021SLiane Praza goto cleanup; 5597*1f6eb021SLiane Praza } 5598*1f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &ev1) == -1) { 5599*1f6eb021SLiane Praza goto cleanup; 5600*1f6eb021SLiane Praza } 5601*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &ev2) == -1) { 5602*1f6eb021SLiane Praza goto cleanup; 5603*1f6eb021SLiane Praza } 5604*1f6eb021SLiane Praza 5605*1f6eb021SLiane Praza return (_scf_tmpl_add_error(errs, SCF_TERR_PG_REDEFINE, NULL, NULL, 5606*1f6eb021SLiane Praza ev1, ev2, NULL, t_fmri, t_pg_name, t_pg_type, NULL, NULL)); 5607*1f6eb021SLiane Praza cleanup: 5608*1f6eb021SLiane Praza free(ev1); 5609*1f6eb021SLiane Praza free(ev2); 5610*1f6eb021SLiane Praza free(t_fmri); 5611*1f6eb021SLiane Praza free(t_pg_name); 5612*1f6eb021SLiane Praza free(t_pg_type); 5613*1f6eb021SLiane Praza return (-1); 5614*1f6eb021SLiane Praza } 5615*1f6eb021SLiane Praza 5616*1f6eb021SLiane Praza /* 5617*1f6eb021SLiane Praza * return 0 if value is within count ranges constraint. 5618*1f6eb021SLiane Praza * return -1 otherwise 5619*1f6eb021SLiane Praza */ 5620*1f6eb021SLiane Praza static int 5621*1f6eb021SLiane Praza _check_count_ranges(scf_count_ranges_t *cr, uint64_t v) 5622*1f6eb021SLiane Praza { 5623*1f6eb021SLiane Praza int i; 5624*1f6eb021SLiane Praza 5625*1f6eb021SLiane Praza for (i = 0; i < cr->scr_num_ranges; ++i) { 5626*1f6eb021SLiane Praza if (v >= cr->scr_min[i] && 5627*1f6eb021SLiane Praza v <= cr->scr_max[i]) { 5628*1f6eb021SLiane Praza /* value is within ranges constraint */ 5629*1f6eb021SLiane Praza return (0); 5630*1f6eb021SLiane Praza } 5631*1f6eb021SLiane Praza } 5632*1f6eb021SLiane Praza return (-1); 5633*1f6eb021SLiane Praza } 5634*1f6eb021SLiane Praza 5635*1f6eb021SLiane Praza /* 5636*1f6eb021SLiane Praza * return 0 if value is within count ranges constraint. 5637*1f6eb021SLiane Praza * return -1 otherwise 5638*1f6eb021SLiane Praza */ 5639*1f6eb021SLiane Praza static int 5640*1f6eb021SLiane Praza _check_int_ranges(scf_int_ranges_t *ir, int64_t v) 5641*1f6eb021SLiane Praza { 5642*1f6eb021SLiane Praza int i; 5643*1f6eb021SLiane Praza 5644*1f6eb021SLiane Praza for (i = 0; i < ir->sir_num_ranges; ++i) { 5645*1f6eb021SLiane Praza if (v >= ir->sir_min[i] && 5646*1f6eb021SLiane Praza v <= ir->sir_max[i]) { 5647*1f6eb021SLiane Praza /* value is within integer ranges constraint */ 5648*1f6eb021SLiane Praza return (0); 5649*1f6eb021SLiane Praza } 5650*1f6eb021SLiane Praza } 5651*1f6eb021SLiane Praza return (-1); 5652*1f6eb021SLiane Praza } 5653*1f6eb021SLiane Praza 5654*1f6eb021SLiane Praza /* 5655*1f6eb021SLiane Praza * int _value_in_constraint() 5656*1f6eb021SLiane Praza * 5657*1f6eb021SLiane Praza * Checks whether the supplied value violates any of the constraints 5658*1f6eb021SLiane Praza * specified in the supplied property template. If it does, an appropriate 5659*1f6eb021SLiane Praza * error is appended to "errs". pg and prop, if supplied, are used to 5660*1f6eb021SLiane Praza * augment the information in the error. Returns 0 on success. 5661*1f6eb021SLiane Praza * 5662*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 5663*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5664*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5665*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5666*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5667*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5668*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 5669*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5670*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5671*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5672*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5673*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5674*1f6eb021SLiane Praza */ 5675*1f6eb021SLiane Praza static int 5676*1f6eb021SLiane Praza _value_in_constraint(scf_propertygroup_t *pg, scf_property_t *prop, 5677*1f6eb021SLiane Praza const scf_prop_tmpl_t *pt, scf_value_t *value, scf_tmpl_errors_t *errs) 5678*1f6eb021SLiane Praza { 5679*1f6eb021SLiane Praza scf_type_t type, tmpl_type; 5680*1f6eb021SLiane Praza scf_values_t vals; 5681*1f6eb021SLiane Praza scf_tmpl_error_type_t terr_type; 5682*1f6eb021SLiane Praza uint64_t v_count; 5683*1f6eb021SLiane Praza int64_t v_int; 5684*1f6eb021SLiane Praza char *vstr; 5685*1f6eb021SLiane Praza ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 5686*1f6eb021SLiane Praza ssize_t ret = 0; 5687*1f6eb021SLiane Praza char **constraints; 5688*1f6eb021SLiane Praza int n = 0; 5689*1f6eb021SLiane Praza int r; 5690*1f6eb021SLiane Praza int err_flag = 0; 5691*1f6eb021SLiane Praza scf_count_ranges_t cr; 5692*1f6eb021SLiane Praza scf_int_ranges_t ir; 5693*1f6eb021SLiane Praza 5694*1f6eb021SLiane Praza type = scf_value_type(value); 5695*1f6eb021SLiane Praza if (type == SCF_TYPE_INVALID) { 5696*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 5697*1f6eb021SLiane Praza return (-1); 5698*1f6eb021SLiane Praza } 5699*1f6eb021SLiane Praza 5700*1f6eb021SLiane Praza /* Check if template type matches value type. */ 5701*1f6eb021SLiane Praza if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) { 5702*1f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) 5703*1f6eb021SLiane Praza /* type is not wildcarded */ 5704*1f6eb021SLiane Praza return (-1); 5705*1f6eb021SLiane Praza } else if (tmpl_type != type) { 5706*1f6eb021SLiane Praza if (errs != NULL) { 5707*1f6eb021SLiane Praza if (pg == NULL && prop == NULL) { 5708*1f6eb021SLiane Praza if (_add_tmpl_constraint_error(errs, 5709*1f6eb021SLiane Praza SCF_TERR_PROP_TYPE_MISMATCH, NULL, pt, 5710*1f6eb021SLiane Praza NULL, value) == -1) 5711*1f6eb021SLiane Praza return (-1); 5712*1f6eb021SLiane Praza } else { 5713*1f6eb021SLiane Praza if (_add_tmpl_wrong_prop_type_error(errs, pg, 5714*1f6eb021SLiane Praza pt, prop) == -1) 5715*1f6eb021SLiane Praza return (-1); 5716*1f6eb021SLiane Praza } 5717*1f6eb021SLiane Praza } 5718*1f6eb021SLiane Praza return (1); 5719*1f6eb021SLiane Praza } 5720*1f6eb021SLiane Praza 5721*1f6eb021SLiane Praza /* Numeric values should be checked against any range constraints. */ 5722*1f6eb021SLiane Praza switch (type) { 5723*1f6eb021SLiane Praza case SCF_TYPE_COUNT: 5724*1f6eb021SLiane Praza r = scf_value_get_count(value, &v_count); 5725*1f6eb021SLiane Praza assert(r == 0); 5726*1f6eb021SLiane Praza 5727*1f6eb021SLiane Praza if (scf_tmpl_value_count_range_constraints(pt, &cr) != 0) { 5728*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 5729*1f6eb021SLiane Praza break; 5730*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) 5731*1f6eb021SLiane Praza (void) scf_set_error( 5732*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 5733*1f6eb021SLiane Praza return (-1); 5734*1f6eb021SLiane Praza } else { 5735*1f6eb021SLiane Praza if (_check_count_ranges(&cr, v_count) == 0) { 5736*1f6eb021SLiane Praza /* value is within ranges constraint */ 5737*1f6eb021SLiane Praza scf_count_ranges_destroy(&cr); 5738*1f6eb021SLiane Praza return (0); 5739*1f6eb021SLiane Praza } 5740*1f6eb021SLiane Praza scf_count_ranges_destroy(&cr); 5741*1f6eb021SLiane Praza } 5742*1f6eb021SLiane Praza 5743*1f6eb021SLiane Praza /* 5744*1f6eb021SLiane Praza * If we get here, we have a possible constraint 5745*1f6eb021SLiane Praza * violation. 5746*1f6eb021SLiane Praza */ 5747*1f6eb021SLiane Praza err_flag |= 0x1; /* RANGE_VIOLATION, count */ 5748*1f6eb021SLiane Praza break; 5749*1f6eb021SLiane Praza case SCF_TYPE_INTEGER: 5750*1f6eb021SLiane Praza if (scf_value_get_integer(value, &v_int) != 0) 5751*1f6eb021SLiane Praza assert(0); 5752*1f6eb021SLiane Praza if (scf_tmpl_value_int_range_constraints(pt, &ir) != 0) { 5753*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 5754*1f6eb021SLiane Praza break; 5755*1f6eb021SLiane Praza if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED) 5756*1f6eb021SLiane Praza (void) scf_set_error( 5757*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 5758*1f6eb021SLiane Praza return (-1); 5759*1f6eb021SLiane Praza } else { 5760*1f6eb021SLiane Praza if (_check_int_ranges(&ir, v_int) == 0) { 5761*1f6eb021SLiane Praza /* value is within ranges constraint */ 5762*1f6eb021SLiane Praza scf_int_ranges_destroy(&ir); 5763*1f6eb021SLiane Praza return (0); 5764*1f6eb021SLiane Praza } 5765*1f6eb021SLiane Praza scf_int_ranges_destroy(&ir); 5766*1f6eb021SLiane Praza } 5767*1f6eb021SLiane Praza /* 5768*1f6eb021SLiane Praza * If we get here, we have a possible constraint 5769*1f6eb021SLiane Praza * violation. 5770*1f6eb021SLiane Praza */ 5771*1f6eb021SLiane Praza err_flag |= 0x2; /* RANGE_VIOLATION, integer */ 5772*1f6eb021SLiane Praza break; 5773*1f6eb021SLiane Praza default: 5774*1f6eb021SLiane Praza break; 5775*1f6eb021SLiane Praza } 5776*1f6eb021SLiane Praza 5777*1f6eb021SLiane Praza vstr = malloc(sz); 5778*1f6eb021SLiane Praza if (vstr == NULL) { 5779*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 5780*1f6eb021SLiane Praza return (-1); 5781*1f6eb021SLiane Praza } 5782*1f6eb021SLiane Praza 5783*1f6eb021SLiane Praza /* 5784*1f6eb021SLiane Praza * If a set of names is provided, confirm value has one of 5785*1f6eb021SLiane Praza * those names. 5786*1f6eb021SLiane Praza */ 5787*1f6eb021SLiane Praza if (scf_tmpl_value_name_constraints(pt, &vals) != 0) { 5788*1f6eb021SLiane Praza free(vstr); 5789*1f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) { 5790*1f6eb021SLiane Praza return (-1); 5791*1f6eb021SLiane Praza } 5792*1f6eb021SLiane Praza } else { 5793*1f6eb021SLiane Praza r = scf_value_get_as_string_typed(value, type, vstr, sz); 5794*1f6eb021SLiane Praza 5795*1f6eb021SLiane Praza /* 5796*1f6eb021SLiane Praza * All errors (INVALID_ARGUMENT, NOT_SET, TYPE_MISMATCH) 5797*1f6eb021SLiane Praza * should be impossible or already caught above. 5798*1f6eb021SLiane Praza */ 5799*1f6eb021SLiane Praza assert(r > 0); 5800*1f6eb021SLiane Praza 5801*1f6eb021SLiane Praza constraints = vals.values.v_astring; 5802*1f6eb021SLiane Praza for (n = 0; constraints[n] != NULL; ++n) { 5803*1f6eb021SLiane Praza if (strcmp(constraints[n], vstr) == 0) { 5804*1f6eb021SLiane Praza /* value is within constraint */ 5805*1f6eb021SLiane Praza scf_values_destroy(&vals); 5806*1f6eb021SLiane Praza free(vstr); 5807*1f6eb021SLiane Praza return (0); 5808*1f6eb021SLiane Praza } 5809*1f6eb021SLiane Praza } 5810*1f6eb021SLiane Praza /* if we get here, we have a constraint violation */ 5811*1f6eb021SLiane Praza err_flag |= 0x4; /* CONSTRAINT_VIOLATED */ 5812*1f6eb021SLiane Praza scf_values_destroy(&vals); 5813*1f6eb021SLiane Praza free(vstr); 5814*1f6eb021SLiane Praza } 5815*1f6eb021SLiane Praza if (err_flag != 0) 5816*1f6eb021SLiane Praza ret = 1; 5817*1f6eb021SLiane Praza /* register the errors found */ 5818*1f6eb021SLiane Praza if (ret == 1 && errs != NULL) { 5819*1f6eb021SLiane Praza if ((err_flag & 0x1) == 0x1) { 5820*1f6eb021SLiane Praza /* 5821*1f6eb021SLiane Praza * Help make the error more human-friendly. If 5822*1f6eb021SLiane Praza * pg and prop are provided, we know we're 5823*1f6eb021SLiane Praza * validating repository data. If they're not, 5824*1f6eb021SLiane Praza * we're validating a potentially hypothetical 5825*1f6eb021SLiane Praza * value. 5826*1f6eb021SLiane Praza */ 5827*1f6eb021SLiane Praza if (pg == NULL && prop == NULL) 5828*1f6eb021SLiane Praza terr_type = SCF_TERR_VALUE_OUT_OF_RANGE; 5829*1f6eb021SLiane Praza else 5830*1f6eb021SLiane Praza terr_type = SCF_TERR_RANGE_VIOLATION; 5831*1f6eb021SLiane Praza if (_add_tmpl_count_error(errs, terr_type, pg, pt, 5832*1f6eb021SLiane Praza prop, v_count, 0, 0) == -1) 5833*1f6eb021SLiane Praza ret = -1; 5834*1f6eb021SLiane Praza } 5835*1f6eb021SLiane Praza if ((err_flag & 0x2) == 0x2) { 5836*1f6eb021SLiane Praza if (pg == NULL && prop == NULL) 5837*1f6eb021SLiane Praza terr_type = SCF_TERR_VALUE_OUT_OF_RANGE; 5838*1f6eb021SLiane Praza else 5839*1f6eb021SLiane Praza terr_type = SCF_TERR_RANGE_VIOLATION; 5840*1f6eb021SLiane Praza if (_add_tmpl_int_error(errs, terr_type, pg, pt, prop, 5841*1f6eb021SLiane Praza v_int, 0, 0) == -1) 5842*1f6eb021SLiane Praza ret = -1; 5843*1f6eb021SLiane Praza } 5844*1f6eb021SLiane Praza if ((err_flag & 0x4) == 0x4) { 5845*1f6eb021SLiane Praza if (pg == NULL && prop == NULL) 5846*1f6eb021SLiane Praza terr_type = SCF_TERR_INVALID_VALUE; 5847*1f6eb021SLiane Praza else 5848*1f6eb021SLiane Praza terr_type = SCF_TERR_VALUE_CONSTRAINT_VIOLATED; 5849*1f6eb021SLiane Praza if (_add_tmpl_constraint_error(errs, terr_type, pg, 5850*1f6eb021SLiane Praza pt, prop, value) == -1) 5851*1f6eb021SLiane Praza ret = -1; 5852*1f6eb021SLiane Praza } 5853*1f6eb021SLiane Praza } 5854*1f6eb021SLiane Praza return (ret); 5855*1f6eb021SLiane Praza } 5856*1f6eb021SLiane Praza 5857*1f6eb021SLiane Praza /* 5858*1f6eb021SLiane Praza * Returns -1 on failure. Sets scf_error(): 5859*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5860*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5861*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5862*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5863*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5864*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 5865*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5866*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5867*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5868*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5869*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5870*1f6eb021SLiane Praza */ 5871*1f6eb021SLiane Praza int 5872*1f6eb021SLiane Praza scf_tmpl_value_in_constraint(const scf_prop_tmpl_t *pt, scf_value_t *value, 5873*1f6eb021SLiane Praza scf_tmpl_errors_t **errs) 5874*1f6eb021SLiane Praza { 5875*1f6eb021SLiane Praza scf_tmpl_errors_t *e = NULL; 5876*1f6eb021SLiane Praza 5877*1f6eb021SLiane Praza if (errs != NULL) { 5878*1f6eb021SLiane Praza char *fmri; 5879*1f6eb021SLiane Praza 5880*1f6eb021SLiane Praza if ((fmri = _scf_tmpl_get_fmri(pt->prt_t)) == NULL) 5881*1f6eb021SLiane Praza return (-1); 5882*1f6eb021SLiane Praza *errs = _scf_create_errors(fmri, 1); 5883*1f6eb021SLiane Praza free(fmri); 5884*1f6eb021SLiane Praza if (*errs == NULL) 5885*1f6eb021SLiane Praza return (-1); 5886*1f6eb021SLiane Praza e = *errs; 5887*1f6eb021SLiane Praza } 5888*1f6eb021SLiane Praza 5889*1f6eb021SLiane Praza return (_value_in_constraint(NULL, NULL, pt, value, e)); 5890*1f6eb021SLiane Praza } 5891*1f6eb021SLiane Praza 5892*1f6eb021SLiane Praza scf_tmpl_error_t * 5893*1f6eb021SLiane Praza scf_tmpl_next_error(scf_tmpl_errors_t *errs) 5894*1f6eb021SLiane Praza { 5895*1f6eb021SLiane Praza if (errs->tes_index < errs->tes_num_errs) { 5896*1f6eb021SLiane Praza assert(errs->tes_errs[errs->tes_index] != NULL); 5897*1f6eb021SLiane Praza return (errs->tes_errs[errs->tes_index++]); 5898*1f6eb021SLiane Praza } else { 5899*1f6eb021SLiane Praza return (NULL); 5900*1f6eb021SLiane Praza } 5901*1f6eb021SLiane Praza } 5902*1f6eb021SLiane Praza 5903*1f6eb021SLiane Praza void 5904*1f6eb021SLiane Praza scf_tmpl_reset_errors(scf_tmpl_errors_t *errs) 5905*1f6eb021SLiane Praza { 5906*1f6eb021SLiane Praza errs->tes_index = 0; 5907*1f6eb021SLiane Praza } 5908*1f6eb021SLiane Praza 5909*1f6eb021SLiane Praza int 5910*1f6eb021SLiane Praza scf_tmpl_strerror(scf_tmpl_error_t *err, char *s, size_t n, int flag) 5911*1f6eb021SLiane Praza { 5912*1f6eb021SLiane Praza const char *str; 5913*1f6eb021SLiane Praza int i; 5914*1f6eb021SLiane Praza int ret = -1; 5915*1f6eb021SLiane Praza int nsz = 0; /* err msg length */ 5916*1f6eb021SLiane Praza int sz = n; /* available buffer size */ 5917*1f6eb021SLiane Praza char *buf = s; /* where to append in buffer */ 5918*1f6eb021SLiane Praza char *s0 = (flag == SCF_TMPL_STRERROR_HUMAN) ? ":\n\t" : ": "; 5919*1f6eb021SLiane Praza char *s1 = (flag == SCF_TMPL_STRERROR_HUMAN) ? "\n\t" : "; "; 5920*1f6eb021SLiane Praza char *sep = s0; 5921*1f6eb021SLiane Praza const char *val; 5922*1f6eb021SLiane Praza 5923*1f6eb021SLiane Praza /* prefix */ 5924*1f6eb021SLiane Praza if (err->te_errs->tes_prefix != NULL) { 5925*1f6eb021SLiane Praza ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN, 5926*1f6eb021SLiane Praza err->te_errs->tes_prefix)); 5927*1f6eb021SLiane Praza nsz += ret; 5928*1f6eb021SLiane Praza sz = (sz - ret) > 0 ? sz - ret : 0; 5929*1f6eb021SLiane Praza buf = (sz > 0) ? s + nsz : NULL; 5930*1f6eb021SLiane Praza } 5931*1f6eb021SLiane Praza /* error message */ 5932*1f6eb021SLiane Praza ret = snprintf(buf, sz, "%s", dgettext(TEXT_DOMAIN, 5933*1f6eb021SLiane Praza em_desc[err->te_type].em_msg)); 5934*1f6eb021SLiane Praza nsz += ret; 5935*1f6eb021SLiane Praza sz = (sz - ret) > 0 ? sz - ret : 0; 5936*1f6eb021SLiane Praza buf = (sz > 0) ? s + nsz : NULL; 5937*1f6eb021SLiane Praza 5938*1f6eb021SLiane Praza for (i = 0; _tmpl_error_items[i].get_desc != NULL; ++i) { 5939*1f6eb021SLiane Praza if ((str = _tmpl_error_items[i].get_desc(err)) == NULL) 5940*1f6eb021SLiane Praza /* no item to print */ 5941*1f6eb021SLiane Praza continue; 5942*1f6eb021SLiane Praza val = _tmpl_error_items[i].get_val(err); 5943*1f6eb021SLiane Praza ret = snprintf(buf, sz, "%s%s=\"%s\"", sep, str, 5944*1f6eb021SLiane Praza (val == NULL) ? "" : val); 5945*1f6eb021SLiane Praza nsz += ret; 5946*1f6eb021SLiane Praza sz = (sz - ret) > 0 ? sz - ret : 0; 5947*1f6eb021SLiane Praza buf = (sz > 0) ? s + nsz : NULL; 5948*1f6eb021SLiane Praza sep = s1; 5949*1f6eb021SLiane Praza } 5950*1f6eb021SLiane Praza return (nsz); 5951*1f6eb021SLiane Praza } 5952*1f6eb021SLiane Praza 5953*1f6eb021SLiane Praza /* 5954*1f6eb021SLiane Praza * return 0 on success, -1 on failure. 5955*1f6eb021SLiane Praza * set scf_error() to: 5956*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 5957*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 5958*1f6eb021SLiane Praza * SCF_ERROR_DELETED 5959*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 5960*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 5961*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 5962*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 5963*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 5964*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 5965*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 5966*1f6eb021SLiane Praza */ 5967*1f6eb021SLiane Praza static int 5968*1f6eb021SLiane Praza _validate_cardinality(scf_propertygroup_t *pg, scf_prop_tmpl_t *pt, 5969*1f6eb021SLiane Praza scf_property_t *prop, scf_tmpl_errors_t *errs) 5970*1f6eb021SLiane Praza { 5971*1f6eb021SLiane Praza uint64_t min, max; 5972*1f6eb021SLiane Praza scf_handle_t *h; 5973*1f6eb021SLiane Praza scf_iter_t *iter = NULL; 5974*1f6eb021SLiane Praza scf_value_t *val = NULL; 5975*1f6eb021SLiane Praza int count = 0; 5976*1f6eb021SLiane Praza int ret = -1; 5977*1f6eb021SLiane Praza int r; 5978*1f6eb021SLiane Praza 5979*1f6eb021SLiane Praza if (scf_tmpl_prop_cardinality(pt, &min, &max) != 0) { 5980*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 5981*1f6eb021SLiane Praza return (0); 5982*1f6eb021SLiane Praza else 5983*1f6eb021SLiane Praza return (-1); 5984*1f6eb021SLiane Praza } 5985*1f6eb021SLiane Praza 5986*1f6eb021SLiane Praza /* Any number of values permitted. Just return success. */ 5987*1f6eb021SLiane Praza if (min == 0 && max == UINT64_MAX) { 5988*1f6eb021SLiane Praza return (0); 5989*1f6eb021SLiane Praza } 5990*1f6eb021SLiane Praza 5991*1f6eb021SLiane Praza h = scf_property_handle(prop); 5992*1f6eb021SLiane Praza if (h == NULL) { 5993*1f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 5994*1f6eb021SLiane Praza goto cleanup; 5995*1f6eb021SLiane Praza } 5996*1f6eb021SLiane Praza 5997*1f6eb021SLiane Praza iter = scf_iter_create(h); 5998*1f6eb021SLiane Praza val = scf_value_create(h); 5999*1f6eb021SLiane Praza if (iter == NULL || val == NULL) { 6000*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6001*1f6eb021SLiane Praza goto cleanup; 6002*1f6eb021SLiane Praza } else { 6003*1f6eb021SLiane Praza assert(0); 6004*1f6eb021SLiane Praza abort(); 6005*1f6eb021SLiane Praza } 6006*1f6eb021SLiane Praza } 6007*1f6eb021SLiane Praza 6008*1f6eb021SLiane Praza if (scf_iter_property_values(iter, prop) != 0) { 6009*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6010*1f6eb021SLiane Praza goto cleanup; 6011*1f6eb021SLiane Praza } else { 6012*1f6eb021SLiane Praza assert(0); 6013*1f6eb021SLiane Praza abort(); 6014*1f6eb021SLiane Praza } 6015*1f6eb021SLiane Praza } 6016*1f6eb021SLiane Praza 6017*1f6eb021SLiane Praza while ((r = scf_iter_next_value(iter, val)) == 1) 6018*1f6eb021SLiane Praza count++; 6019*1f6eb021SLiane Praza 6020*1f6eb021SLiane Praza if (r < 0) { 6021*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6022*1f6eb021SLiane Praza goto cleanup; 6023*1f6eb021SLiane Praza } else { 6024*1f6eb021SLiane Praza assert(0); 6025*1f6eb021SLiane Praza abort(); 6026*1f6eb021SLiane Praza } 6027*1f6eb021SLiane Praza } 6028*1f6eb021SLiane Praza 6029*1f6eb021SLiane Praza if (count < min || count > max) 6030*1f6eb021SLiane Praza if (_add_tmpl_count_error(errs, SCF_TERR_CARDINALITY_VIOLATION, 6031*1f6eb021SLiane Praza pg, pt, prop, (uint64_t)count, &min, &max) == -1) 6032*1f6eb021SLiane Praza goto cleanup; 6033*1f6eb021SLiane Praza 6034*1f6eb021SLiane Praza ret = 0; 6035*1f6eb021SLiane Praza 6036*1f6eb021SLiane Praza cleanup: 6037*1f6eb021SLiane Praza scf_iter_destroy(iter); 6038*1f6eb021SLiane Praza scf_value_destroy(val); 6039*1f6eb021SLiane Praza return (ret); 6040*1f6eb021SLiane Praza } 6041*1f6eb021SLiane Praza 6042*1f6eb021SLiane Praza /* 6043*1f6eb021SLiane Praza * Returns -1 on error. Sets scf_error(): 6044*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 6045*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 6046*1f6eb021SLiane Praza * SCF_ERROR_DELETED 6047*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 6048*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 6049*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 6050*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 6051*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 6052*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 6053*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 6054*1f6eb021SLiane Praza */ 6055*1f6eb021SLiane Praza static int 6056*1f6eb021SLiane Praza _check_property(scf_prop_tmpl_t *pt, scf_propertygroup_t *pg, 6057*1f6eb021SLiane Praza scf_property_t *prop, scf_tmpl_errors_t *errs) 6058*1f6eb021SLiane Praza { 6059*1f6eb021SLiane Praza scf_type_t tmpl_type; 6060*1f6eb021SLiane Praza uint8_t required; 6061*1f6eb021SLiane Praza scf_handle_t *h; 6062*1f6eb021SLiane Praza scf_iter_t *iter = NULL; 6063*1f6eb021SLiane Praza scf_value_t *val = NULL; 6064*1f6eb021SLiane Praza int r; 6065*1f6eb021SLiane Praza int ret = -1; 6066*1f6eb021SLiane Praza 6067*1f6eb021SLiane Praza h = scf_pg_handle(pg); 6068*1f6eb021SLiane Praza if (h == NULL) { 6069*1f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 6070*1f6eb021SLiane Praza return (-1); 6071*1f6eb021SLiane Praza } 6072*1f6eb021SLiane Praza 6073*1f6eb021SLiane Praza iter = scf_iter_create(h); 6074*1f6eb021SLiane Praza val = scf_value_create(h); 6075*1f6eb021SLiane Praza if (iter == NULL || val == NULL) { 6076*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6077*1f6eb021SLiane Praza scf_iter_destroy(iter); 6078*1f6eb021SLiane Praza scf_value_destroy(val); 6079*1f6eb021SLiane Praza return (-1); 6080*1f6eb021SLiane Praza } else { 6081*1f6eb021SLiane Praza assert(0); 6082*1f6eb021SLiane Praza abort(); 6083*1f6eb021SLiane Praza } 6084*1f6eb021SLiane Praza } 6085*1f6eb021SLiane Praza 6086*1f6eb021SLiane Praza if (scf_tmpl_prop_required(pt, &required) != 0) 6087*1f6eb021SLiane Praza goto cleanup; 6088*1f6eb021SLiane Praza 6089*1f6eb021SLiane Praza /* Check type */ 6090*1f6eb021SLiane Praza if (scf_tmpl_prop_type(pt, &tmpl_type) == -1) { 6091*1f6eb021SLiane Praza if (scf_error() != SCF_ERROR_NOT_FOUND) { 6092*1f6eb021SLiane Praza goto cleanup; 6093*1f6eb021SLiane Praza } else if (required) { 6094*1f6eb021SLiane Praza /* If required, type must be specified. */ 6095*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 6096*1f6eb021SLiane Praza goto cleanup; 6097*1f6eb021SLiane Praza } 6098*1f6eb021SLiane Praza } else if (scf_property_is_type(prop, tmpl_type) != 0) { 6099*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6100*1f6eb021SLiane Praza goto cleanup; 6101*1f6eb021SLiane Praza } else switch (scf_error()) { 6102*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 6103*1f6eb021SLiane Praza if (_add_tmpl_wrong_prop_type_error(errs, pg, pt, 6104*1f6eb021SLiane Praza prop) == -1) 6105*1f6eb021SLiane Praza goto cleanup; 6106*1f6eb021SLiane Praza break; 6107*1f6eb021SLiane Praza 6108*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6109*1f6eb021SLiane Praza /* 6110*1f6eb021SLiane Praza * tmpl_prop_type shouldn't have handed back 6111*1f6eb021SLiane Praza * an invalid property type. 6112*1f6eb021SLiane Praza */ 6113*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 6114*1f6eb021SLiane Praza default: 6115*1f6eb021SLiane Praza assert(0); 6116*1f6eb021SLiane Praza abort(); 6117*1f6eb021SLiane Praza } 6118*1f6eb021SLiane Praza } 6119*1f6eb021SLiane Praza 6120*1f6eb021SLiane Praza 6121*1f6eb021SLiane Praza /* Cardinality */ 6122*1f6eb021SLiane Praza if (_validate_cardinality(pg, pt, prop, errs) == -1) 6123*1f6eb021SLiane Praza goto cleanup; 6124*1f6eb021SLiane Praza 6125*1f6eb021SLiane Praza /* Value constraints */ 6126*1f6eb021SLiane Praza /* 6127*1f6eb021SLiane Praza * Iterate through each value, and confirm it is defined as 6128*1f6eb021SLiane Praza * constrained. 6129*1f6eb021SLiane Praza */ 6130*1f6eb021SLiane Praza if (scf_iter_property_values(iter, prop) != 0) { 6131*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET && 6132*1f6eb021SLiane Praza scf_error() != SCF_ERROR_HANDLE_MISMATCH); 6133*1f6eb021SLiane Praza goto cleanup; 6134*1f6eb021SLiane Praza } 6135*1f6eb021SLiane Praza 6136*1f6eb021SLiane Praza while ((r = scf_iter_next_value(iter, val)) == 1) { 6137*1f6eb021SLiane Praza if (_value_in_constraint(pg, prop, pt, val, errs) == -1) { 6138*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6139*1f6eb021SLiane Praza goto cleanup; 6140*1f6eb021SLiane Praza } else switch (scf_error()) { 6141*1f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 6142*1f6eb021SLiane Praza goto cleanup; 6143*1f6eb021SLiane Praza 6144*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6145*1f6eb021SLiane Praza default: 6146*1f6eb021SLiane Praza assert(0); 6147*1f6eb021SLiane Praza abort(); 6148*1f6eb021SLiane Praza } 6149*1f6eb021SLiane Praza } 6150*1f6eb021SLiane Praza } 6151*1f6eb021SLiane Praza 6152*1f6eb021SLiane Praza if (r < 0) { 6153*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6154*1f6eb021SLiane Praza goto cleanup; 6155*1f6eb021SLiane Praza } else { 6156*1f6eb021SLiane Praza assert(0); 6157*1f6eb021SLiane Praza abort(); 6158*1f6eb021SLiane Praza } 6159*1f6eb021SLiane Praza } 6160*1f6eb021SLiane Praza 6161*1f6eb021SLiane Praza ret = 0; 6162*1f6eb021SLiane Praza 6163*1f6eb021SLiane Praza cleanup: 6164*1f6eb021SLiane Praza scf_iter_destroy(iter); 6165*1f6eb021SLiane Praza scf_value_destroy(val); 6166*1f6eb021SLiane Praza return (ret); 6167*1f6eb021SLiane Praza } 6168*1f6eb021SLiane Praza 6169*1f6eb021SLiane Praza /* 6170*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 6171*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 6172*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 6173*1f6eb021SLiane Praza * SCF_ERROR_DELETED 6174*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 6175*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 6176*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 6177*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 6178*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 6179*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 6180*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 6181*1f6eb021SLiane Praza */ 6182*1f6eb021SLiane Praza static int 6183*1f6eb021SLiane Praza _check_pg(scf_pg_tmpl_t *t, scf_propertygroup_t *pg, char *pg_name, 6184*1f6eb021SLiane Praza char *type, scf_tmpl_errors_t *errs) 6185*1f6eb021SLiane Praza { 6186*1f6eb021SLiane Praza scf_prop_tmpl_t *pt = NULL; 6187*1f6eb021SLiane Praza char *pg_type = NULL; 6188*1f6eb021SLiane Praza scf_iter_t *iter = NULL; 6189*1f6eb021SLiane Praza uint8_t pg_required; 6190*1f6eb021SLiane Praza scf_property_t *prop = NULL; 6191*1f6eb021SLiane Praza scf_handle_t *h; 6192*1f6eb021SLiane Praza int r; 6193*1f6eb021SLiane Praza char *prop_name = NULL; 6194*1f6eb021SLiane Praza ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 6195*1f6eb021SLiane Praza int ret = -1; 6196*1f6eb021SLiane Praza 6197*1f6eb021SLiane Praza assert(pg_name != NULL); 6198*1f6eb021SLiane Praza assert(t != NULL); 6199*1f6eb021SLiane Praza assert(pg != NULL); 6200*1f6eb021SLiane Praza assert(type != NULL); 6201*1f6eb021SLiane Praza assert(nsize != 0); 6202*1f6eb021SLiane Praza 6203*1f6eb021SLiane Praza if ((h = scf_pg_handle(pg)) == NULL) { 6204*1f6eb021SLiane Praza assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED); 6205*1f6eb021SLiane Praza return (-1); 6206*1f6eb021SLiane Praza } 6207*1f6eb021SLiane Praza if ((pt = scf_tmpl_prop_create(h)) == NULL) { 6208*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 6209*1f6eb021SLiane Praza return (-1); 6210*1f6eb021SLiane Praza } 6211*1f6eb021SLiane Praza 6212*1f6eb021SLiane Praza if ((prop = scf_property_create(h)) == NULL) { 6213*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 6214*1f6eb021SLiane Praza goto cleanup; 6215*1f6eb021SLiane Praza } 6216*1f6eb021SLiane Praza 6217*1f6eb021SLiane Praza if ((iter = scf_iter_create(h)) == NULL) { 6218*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT); 6219*1f6eb021SLiane Praza goto cleanup; 6220*1f6eb021SLiane Praza } 6221*1f6eb021SLiane Praza if ((prop_name = malloc(nsize)) == NULL) { 6222*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 6223*1f6eb021SLiane Praza goto cleanup; 6224*1f6eb021SLiane Praza } 6225*1f6eb021SLiane Praza 6226*1f6eb021SLiane Praza if (scf_tmpl_pg_required(t, &pg_required) != 0) 6227*1f6eb021SLiane Praza goto cleanup; 6228*1f6eb021SLiane Praza 6229*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &pg_type) == -1) { 6230*1f6eb021SLiane Praza goto cleanup; 6231*1f6eb021SLiane Praza } else if (pg_required != 0 && 6232*1f6eb021SLiane Praza strcmp(SCF_TMPL_WILDCARD, pg_type) == 0) { 6233*1f6eb021SLiane Praza /* Type must be specified for required pgs. */ 6234*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 6235*1f6eb021SLiane Praza goto cleanup; 6236*1f6eb021SLiane Praza } 6237*1f6eb021SLiane Praza 6238*1f6eb021SLiane Praza if (pg_type != NULL) { 6239*1f6eb021SLiane Praza if (strcmp(pg_type, type) != 0 && 6240*1f6eb021SLiane Praza strcmp(pg_type, SCF_TMPL_WILDCARD) != 0) { 6241*1f6eb021SLiane Praza if (_add_tmpl_wrong_pg_type_error(errs, t, pg) == -1) 6242*1f6eb021SLiane Praza goto cleanup; 6243*1f6eb021SLiane Praza } 6244*1f6eb021SLiane Praza } 6245*1f6eb021SLiane Praza 6246*1f6eb021SLiane Praza 6247*1f6eb021SLiane Praza /* Iterate through properties in the repository and check them. */ 6248*1f6eb021SLiane Praza if (scf_iter_pg_properties(iter, pg) != 0) { 6249*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6250*1f6eb021SLiane Praza goto cleanup; 6251*1f6eb021SLiane Praza } else { 6252*1f6eb021SLiane Praza assert(0); 6253*1f6eb021SLiane Praza abort(); 6254*1f6eb021SLiane Praza } 6255*1f6eb021SLiane Praza } 6256*1f6eb021SLiane Praza 6257*1f6eb021SLiane Praza while ((r = scf_iter_next_property(iter, prop)) == 1) { 6258*1f6eb021SLiane Praza if (scf_property_get_name(prop, prop_name, nsize) == -1) { 6259*1f6eb021SLiane Praza assert(scf_error() != SCF_ERROR_NOT_SET); 6260*1f6eb021SLiane Praza goto cleanup; 6261*1f6eb021SLiane Praza } 6262*1f6eb021SLiane Praza if (scf_tmpl_get_by_prop(t, prop_name, pt, 0) != 0) { 6263*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6264*1f6eb021SLiane Praza goto cleanup; 6265*1f6eb021SLiane Praza } else switch (scf_error()) { 6266*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6267*1f6eb021SLiane Praza /* No template. Continue. */ 6268*1f6eb021SLiane Praza continue; 6269*1f6eb021SLiane Praza 6270*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6271*1f6eb021SLiane Praza default: 6272*1f6eb021SLiane Praza assert(0); 6273*1f6eb021SLiane Praza abort(); 6274*1f6eb021SLiane Praza } 6275*1f6eb021SLiane Praza } 6276*1f6eb021SLiane Praza 6277*1f6eb021SLiane Praza if (_check_property(pt, pg, prop, errs) != 0) 6278*1f6eb021SLiane Praza goto cleanup; 6279*1f6eb021SLiane Praza } 6280*1f6eb021SLiane Praza 6281*1f6eb021SLiane Praza if (r < 0) { 6282*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6283*1f6eb021SLiane Praza goto cleanup; 6284*1f6eb021SLiane Praza } else { 6285*1f6eb021SLiane Praza assert(0); 6286*1f6eb021SLiane Praza abort(); 6287*1f6eb021SLiane Praza } 6288*1f6eb021SLiane Praza } 6289*1f6eb021SLiane Praza 6290*1f6eb021SLiane Praza scf_tmpl_prop_reset(pt); 6291*1f6eb021SLiane Praza free(prop_name); 6292*1f6eb021SLiane Praza prop_name = NULL; 6293*1f6eb021SLiane Praza /* 6294*1f6eb021SLiane Praza * Confirm required properties are present. 6295*1f6eb021SLiane Praza */ 6296*1f6eb021SLiane Praza while ((r = scf_tmpl_iter_props(t, pt, 6297*1f6eb021SLiane Praza SCF_PROP_TMPL_FLAG_REQUIRED)) == 0) { 6298*1f6eb021SLiane Praza scf_type_t prop_type; 6299*1f6eb021SLiane Praza 6300*1f6eb021SLiane Praza if (scf_tmpl_prop_name(pt, &prop_name) == -1) 6301*1f6eb021SLiane Praza goto cleanup; 6302*1f6eb021SLiane Praza 6303*1f6eb021SLiane Praza /* required properties cannot have type wildcarded */ 6304*1f6eb021SLiane Praza if (scf_tmpl_prop_type(pt, &prop_type) == -1) { 6305*1f6eb021SLiane Praza if (scf_error() == SCF_ERROR_NOT_FOUND) 6306*1f6eb021SLiane Praza (void) scf_set_error( 6307*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 6308*1f6eb021SLiane Praza goto cleanup; 6309*1f6eb021SLiane Praza } 6310*1f6eb021SLiane Praza 6311*1f6eb021SLiane Praza if (scf_pg_get_property(pg, prop_name, prop) != 0) { 6312*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6313*1f6eb021SLiane Praza goto cleanup; 6314*1f6eb021SLiane Praza } else switch (scf_error()) { 6315*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6316*1f6eb021SLiane Praza if (_add_tmpl_missing_prop_error(errs, t, pg, 6317*1f6eb021SLiane Praza pt) == -1) 6318*1f6eb021SLiane Praza goto cleanup; 6319*1f6eb021SLiane Praza break; 6320*1f6eb021SLiane Praza 6321*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6322*1f6eb021SLiane Praza (void) scf_set_error( 6323*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 6324*1f6eb021SLiane Praza goto cleanup; 6325*1f6eb021SLiane Praza 6326*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 6327*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 6328*1f6eb021SLiane Praza default: 6329*1f6eb021SLiane Praza assert(0); 6330*1f6eb021SLiane Praza abort(); 6331*1f6eb021SLiane Praza } 6332*1f6eb021SLiane Praza } 6333*1f6eb021SLiane Praza free(prop_name); 6334*1f6eb021SLiane Praza prop_name = NULL; 6335*1f6eb021SLiane Praza } 6336*1f6eb021SLiane Praza if (r < 0) { 6337*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6338*1f6eb021SLiane Praza goto cleanup; 6339*1f6eb021SLiane Praza } else switch (scf_error()) { 6340*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6341*1f6eb021SLiane Praza break; 6342*1f6eb021SLiane Praza 6343*1f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 6344*1f6eb021SLiane Praza goto cleanup; 6345*1f6eb021SLiane Praza 6346*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6347*1f6eb021SLiane Praza default: 6348*1f6eb021SLiane Praza assert(0); 6349*1f6eb021SLiane Praza abort(); 6350*1f6eb021SLiane Praza } 6351*1f6eb021SLiane Praza } 6352*1f6eb021SLiane Praza 6353*1f6eb021SLiane Praza ret = 0; 6354*1f6eb021SLiane Praza cleanup: 6355*1f6eb021SLiane Praza scf_tmpl_prop_destroy(pt); 6356*1f6eb021SLiane Praza scf_iter_destroy(iter); 6357*1f6eb021SLiane Praza scf_property_destroy(prop); 6358*1f6eb021SLiane Praza free(prop_name); 6359*1f6eb021SLiane Praza free(pg_type); 6360*1f6eb021SLiane Praza return (ret); 6361*1f6eb021SLiane Praza } 6362*1f6eb021SLiane Praza 6363*1f6eb021SLiane Praza /* 6364*1f6eb021SLiane Praza * Checks if instance fmri redefines any pgs defined in restarter or global 6365*1f6eb021SLiane Praza * Return -1 on failure, sets scf_error() to: 6366*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 6367*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 6368*1f6eb021SLiane Praza * SCF_ERROR_DELETED 6369*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 6370*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 6371*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 6372*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 6373*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 6374*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 6375*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 6376*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 6377*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 6378*1f6eb021SLiane Praza */ 6379*1f6eb021SLiane Praza static int 6380*1f6eb021SLiane Praza _scf_tmpl_check_pg_redef(scf_handle_t *h, const char *fmri, 6381*1f6eb021SLiane Praza const char *snapname, scf_tmpl_errors_t *errs) 6382*1f6eb021SLiane Praza { 6383*1f6eb021SLiane Praza scf_pg_tmpl_t *t = NULL; 6384*1f6eb021SLiane Praza scf_pg_tmpl_t *r = NULL; 6385*1f6eb021SLiane Praza char *pg_name = NULL; 6386*1f6eb021SLiane Praza char *pg_name_r = NULL; 6387*1f6eb021SLiane Praza char *pg_type = NULL; 6388*1f6eb021SLiane Praza char *pg_type_r = NULL; 6389*1f6eb021SLiane Praza char *target = NULL; 6390*1f6eb021SLiane Praza int ret_val = -1; 6391*1f6eb021SLiane Praza int ret; 6392*1f6eb021SLiane Praza 6393*1f6eb021SLiane Praza t = scf_tmpl_pg_create(h); 6394*1f6eb021SLiane Praza r = scf_tmpl_pg_create(h); 6395*1f6eb021SLiane Praza if (t == NULL || r == NULL) 6396*1f6eb021SLiane Praza goto cleanup; 6397*1f6eb021SLiane Praza 6398*1f6eb021SLiane Praza while ((ret = scf_tmpl_iter_pgs(t, fmri, snapname, NULL, 6399*1f6eb021SLiane Praza SCF_PG_TMPL_FLAG_EXACT)) == 1) { 6400*1f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &pg_name) == -1) { 6401*1f6eb021SLiane Praza goto cleanup; 6402*1f6eb021SLiane Praza } 6403*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &pg_type) == -1) { 6404*1f6eb021SLiane Praza goto cleanup; 6405*1f6eb021SLiane Praza } 6406*1f6eb021SLiane Praza /* look for a redefinition of a global/restarter pg_pattern */ 6407*1f6eb021SLiane Praza while ((ret = scf_tmpl_iter_pgs(r, fmri, snapname, pg_type, 6408*1f6eb021SLiane Praza 0)) == 1) { 6409*1f6eb021SLiane Praza if (scf_tmpl_pg_name(r, &pg_name_r) == -1) { 6410*1f6eb021SLiane Praza goto cleanup; 6411*1f6eb021SLiane Praza } else if (strcmp(pg_name_r, SCF_TMPL_WILDCARD) != 0 && 6412*1f6eb021SLiane Praza strcmp(pg_name, SCF_TMPL_WILDCARD) != 0 && 6413*1f6eb021SLiane Praza strcmp(pg_name, pg_name_r) != 0) { 6414*1f6eb021SLiane Praza /* not a match */ 6415*1f6eb021SLiane Praza free(pg_name_r); 6416*1f6eb021SLiane Praza pg_name_r = NULL; 6417*1f6eb021SLiane Praza continue; 6418*1f6eb021SLiane Praza } 6419*1f6eb021SLiane Praza if (scf_tmpl_pg_type(r, &pg_type_r) == -1) { 6420*1f6eb021SLiane Praza goto cleanup; 6421*1f6eb021SLiane Praza } else if (strcmp(pg_type_r, SCF_TMPL_WILDCARD) != 0 && 6422*1f6eb021SLiane Praza strcmp(pg_type, SCF_TMPL_WILDCARD) != 0 && 6423*1f6eb021SLiane Praza strcmp(pg_type, pg_type_r) != 0) { 6424*1f6eb021SLiane Praza /* not a match */ 6425*1f6eb021SLiane Praza free(pg_name_r); 6426*1f6eb021SLiane Praza pg_name_r = NULL; 6427*1f6eb021SLiane Praza free(pg_type_r); 6428*1f6eb021SLiane Praza pg_type_r = NULL; 6429*1f6eb021SLiane Praza continue; 6430*1f6eb021SLiane Praza } 6431*1f6eb021SLiane Praza if (scf_tmpl_pg_target(r, &target) == -1) { 6432*1f6eb021SLiane Praza target = NULL; 6433*1f6eb021SLiane Praza goto cleanup; 6434*1f6eb021SLiane Praza } 6435*1f6eb021SLiane Praza if (strcmp(target, SCF_TM_TARGET_ALL) == 0 || 6436*1f6eb021SLiane Praza strcmp(target, SCF_TM_TARGET_DELEGATE) == 0) { 6437*1f6eb021SLiane Praza /* found a pg_pattern redefinition */ 6438*1f6eb021SLiane Praza if (_add_tmpl_pg_redefine_error(errs, t, 6439*1f6eb021SLiane Praza r) == -1) 6440*1f6eb021SLiane Praza goto cleanup; 6441*1f6eb021SLiane Praza free(pg_name_r); 6442*1f6eb021SLiane Praza pg_name_r = NULL; 6443*1f6eb021SLiane Praza free(target); 6444*1f6eb021SLiane Praza target = NULL; 6445*1f6eb021SLiane Praza break; 6446*1f6eb021SLiane Praza } 6447*1f6eb021SLiane Praza free(pg_name_r); 6448*1f6eb021SLiane Praza pg_name_r = NULL; 6449*1f6eb021SLiane Praza free(target); 6450*1f6eb021SLiane Praza target = NULL; 6451*1f6eb021SLiane Praza } 6452*1f6eb021SLiane Praza if (ret == -1) 6453*1f6eb021SLiane Praza goto cleanup; 6454*1f6eb021SLiane Praza scf_tmpl_pg_reset(r); 6455*1f6eb021SLiane Praza 6456*1f6eb021SLiane Praza free(pg_name); 6457*1f6eb021SLiane Praza free(pg_type); 6458*1f6eb021SLiane Praza pg_name = NULL; 6459*1f6eb021SLiane Praza pg_type = NULL; 6460*1f6eb021SLiane Praza } 6461*1f6eb021SLiane Praza if (ret == -1) 6462*1f6eb021SLiane Praza goto cleanup; 6463*1f6eb021SLiane Praza 6464*1f6eb021SLiane Praza ret_val = 0; 6465*1f6eb021SLiane Praza 6466*1f6eb021SLiane Praza cleanup: 6467*1f6eb021SLiane Praza scf_tmpl_pg_destroy(t); 6468*1f6eb021SLiane Praza scf_tmpl_pg_destroy(r); 6469*1f6eb021SLiane Praza free(pg_name); 6470*1f6eb021SLiane Praza free(pg_type); 6471*1f6eb021SLiane Praza free(pg_name_r); 6472*1f6eb021SLiane Praza free(pg_type_r); 6473*1f6eb021SLiane Praza free(target); 6474*1f6eb021SLiane Praza 6475*1f6eb021SLiane Praza if (ret_val == -1) { 6476*1f6eb021SLiane Praza if (!ismember(scf_error(), errors_server)) { 6477*1f6eb021SLiane Praza switch (scf_error()) { 6478*1f6eb021SLiane Praza case SCF_ERROR_TYPE_MISMATCH: 6479*1f6eb021SLiane Praza (void) scf_set_error( 6480*1f6eb021SLiane Praza SCF_ERROR_TEMPLATE_INVALID); 6481*1f6eb021SLiane Praza /*FALLTHROUGH*/ 6482*1f6eb021SLiane Praza 6483*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 6484*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6485*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6486*1f6eb021SLiane Praza case SCF_ERROR_TEMPLATE_INVALID: 6487*1f6eb021SLiane Praza break; 6488*1f6eb021SLiane Praza 6489*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 6490*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 6491*1f6eb021SLiane Praza default: 6492*1f6eb021SLiane Praza assert(0); 6493*1f6eb021SLiane Praza abort(); 6494*1f6eb021SLiane Praza } 6495*1f6eb021SLiane Praza } 6496*1f6eb021SLiane Praza } 6497*1f6eb021SLiane Praza return (ret_val); 6498*1f6eb021SLiane Praza } 6499*1f6eb021SLiane Praza 6500*1f6eb021SLiane Praza /* 6501*1f6eb021SLiane Praza * Returns -1 on failure, sets scf_error() to: 6502*1f6eb021SLiane Praza * SCF_ERROR_BACKEND_ACCESS 6503*1f6eb021SLiane Praza * SCF_ERROR_CONNECTION_BROKEN 6504*1f6eb021SLiane Praza * SCF_ERROR_DELETED 6505*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED 6506*1f6eb021SLiane Praza * SCF_ERROR_INTERNAL 6507*1f6eb021SLiane Praza * SCF_ERROR_INVALID_ARGUMENT 6508*1f6eb021SLiane Praza * SCF_ERROR_NO_MEMORY 6509*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES 6510*1f6eb021SLiane Praza * SCF_ERROR_NOT_BOUND 6511*1f6eb021SLiane Praza * SCF_ERROR_NOT_FOUND 6512*1f6eb021SLiane Praza * SCF_ERROR_PERMISSION_DENIED 6513*1f6eb021SLiane Praza * SCF_ERROR_TEMPLATE_INVALID 6514*1f6eb021SLiane Praza */ 6515*1f6eb021SLiane Praza int 6516*1f6eb021SLiane Praza scf_tmpl_validate_fmri(scf_handle_t *h, const char *fmri, const char *snapshot, 6517*1f6eb021SLiane Praza scf_tmpl_errors_t **errs, int flags) 6518*1f6eb021SLiane Praza { 6519*1f6eb021SLiane Praza scf_pg_tmpl_t *t = NULL; 6520*1f6eb021SLiane Praza scf_iter_t *iter = NULL; 6521*1f6eb021SLiane Praza scf_propertygroup_t *pg = NULL; 6522*1f6eb021SLiane Praza scf_instance_t *inst = NULL; 6523*1f6eb021SLiane Praza scf_snapshot_t *snap = NULL; 6524*1f6eb021SLiane Praza char *type = NULL; 6525*1f6eb021SLiane Praza char *pg_name = NULL; 6526*1f6eb021SLiane Praza ssize_t rsize = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1; 6527*1f6eb021SLiane Praza ssize_t nsize = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 6528*1f6eb021SLiane Praza int ret = -1; 6529*1f6eb021SLiane Praza int r; 6530*1f6eb021SLiane Praza 6531*1f6eb021SLiane Praza assert(errs != NULL); 6532*1f6eb021SLiane Praza 6533*1f6eb021SLiane Praza if ((*errs = _scf_create_errors(fmri, 1)) == NULL) 6534*1f6eb021SLiane Praza return (-1); 6535*1f6eb021SLiane Praza 6536*1f6eb021SLiane Praza if ((pg = scf_pg_create(h)) == NULL || 6537*1f6eb021SLiane Praza (iter = scf_iter_create(h)) == NULL || 6538*1f6eb021SLiane Praza (inst = scf_instance_create(h)) == NULL || 6539*1f6eb021SLiane Praza (t = scf_tmpl_pg_create(h)) == NULL) { 6540*1f6eb021SLiane Praza /* 6541*1f6eb021SLiane Praza * Sets SCF_ERROR_INVALID_ARGUMENT, SCF_ERROR_NO_MEMORY, 6542*1f6eb021SLiane Praza * SCF_ERROR_NO_RESOURCES, SCF_ERROR_INTERNAL or 6543*1f6eb021SLiane Praza * SCF_ERROR_HANDLE_DESTROYED. 6544*1f6eb021SLiane Praza */ 6545*1f6eb021SLiane Praza goto cleanup; 6546*1f6eb021SLiane Praza } 6547*1f6eb021SLiane Praza 6548*1f6eb021SLiane Praza if ((type = malloc(rsize)) == NULL || 6549*1f6eb021SLiane Praza (pg_name = malloc(nsize)) == NULL) { 6550*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NO_MEMORY); 6551*1f6eb021SLiane Praza goto cleanup; 6552*1f6eb021SLiane Praza } 6553*1f6eb021SLiane Praza 6554*1f6eb021SLiane Praza if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, NULL, 6555*1f6eb021SLiane Praza SCF_DECODE_FMRI_EXACT|SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 6556*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6557*1f6eb021SLiane Praza goto cleanup; 6558*1f6eb021SLiane Praza } else switch (scf_error()) { 6559*1f6eb021SLiane Praza case SCF_ERROR_CONSTRAINT_VIOLATED: 6560*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 6561*1f6eb021SLiane Praza /*FALLTHROUGH*/ 6562*1f6eb021SLiane Praza 6563*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6564*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6565*1f6eb021SLiane Praza goto cleanup; 6566*1f6eb021SLiane Praza 6567*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 6568*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 6569*1f6eb021SLiane Praza default: 6570*1f6eb021SLiane Praza assert(0); 6571*1f6eb021SLiane Praza abort(); 6572*1f6eb021SLiane Praza } 6573*1f6eb021SLiane Praza } 6574*1f6eb021SLiane Praza 6575*1f6eb021SLiane Praza if (snapshot == NULL || strcmp(snapshot, "running") == 0 || 6576*1f6eb021SLiane Praza (flags & SCF_TMPL_VALIDATE_FLAG_CURRENT)) { 6577*1f6eb021SLiane Praza if (_get_snapshot(inst, NULL, &snap) == -1) 6578*1f6eb021SLiane Praza goto cleanup; 6579*1f6eb021SLiane Praza } else { 6580*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NONE); 6581*1f6eb021SLiane Praza if (_get_snapshot(inst, snapshot, &snap) == -1) { 6582*1f6eb021SLiane Praza goto cleanup; 6583*1f6eb021SLiane Praza } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 6584*1f6eb021SLiane Praza goto cleanup; 6585*1f6eb021SLiane Praza } 6586*1f6eb021SLiane Praza } 6587*1f6eb021SLiane Praza if (_scf_tmpl_check_pg_redef(h, fmri, snapshot, *errs) != 0) { 6588*1f6eb021SLiane Praza goto cleanup; 6589*1f6eb021SLiane Praza } 6590*1f6eb021SLiane Praza 6591*1f6eb021SLiane Praza /* 6592*1f6eb021SLiane Praza * Check that property groups on this instance conform to the template. 6593*1f6eb021SLiane Praza */ 6594*1f6eb021SLiane Praza if (scf_iter_instance_pgs_composed(iter, inst, snap) != 0) { 6595*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6596*1f6eb021SLiane Praza goto cleanup; 6597*1f6eb021SLiane Praza } else { 6598*1f6eb021SLiane Praza assert(0); 6599*1f6eb021SLiane Praza abort(); 6600*1f6eb021SLiane Praza } 6601*1f6eb021SLiane Praza } 6602*1f6eb021SLiane Praza 6603*1f6eb021SLiane Praza while ((r = scf_iter_next_pg(iter, pg)) == 1) { 6604*1f6eb021SLiane Praza if (scf_pg_get_name(pg, pg_name, nsize) == -1) { 6605*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6606*1f6eb021SLiane Praza goto cleanup; 6607*1f6eb021SLiane Praza } else { 6608*1f6eb021SLiane Praza assert(0); 6609*1f6eb021SLiane Praza abort(); 6610*1f6eb021SLiane Praza } 6611*1f6eb021SLiane Praza } 6612*1f6eb021SLiane Praza 6613*1f6eb021SLiane Praza if (scf_pg_get_type(pg, type, rsize) == -1) { 6614*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6615*1f6eb021SLiane Praza goto cleanup; 6616*1f6eb021SLiane Praza } else { 6617*1f6eb021SLiane Praza assert(0); 6618*1f6eb021SLiane Praza abort(); 6619*1f6eb021SLiane Praza } 6620*1f6eb021SLiane Praza } 6621*1f6eb021SLiane Praza 6622*1f6eb021SLiane Praza if (scf_tmpl_get_by_pg_name(fmri, snapshot, pg_name, type, t, 6623*1f6eb021SLiane Praza 0) != 0) { 6624*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6625*1f6eb021SLiane Praza goto cleanup; 6626*1f6eb021SLiane Praza } else switch (scf_error()) { 6627*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6628*1f6eb021SLiane Praza continue; 6629*1f6eb021SLiane Praza 6630*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6631*1f6eb021SLiane Praza goto cleanup; 6632*1f6eb021SLiane Praza 6633*1f6eb021SLiane Praza default: 6634*1f6eb021SLiane Praza assert(0); 6635*1f6eb021SLiane Praza abort(); 6636*1f6eb021SLiane Praza } 6637*1f6eb021SLiane Praza } 6638*1f6eb021SLiane Praza 6639*1f6eb021SLiane Praza if (_check_pg(t, pg, pg_name, type, *errs) != 0) 6640*1f6eb021SLiane Praza goto cleanup; 6641*1f6eb021SLiane Praza } 6642*1f6eb021SLiane Praza if (r < 0) { 6643*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6644*1f6eb021SLiane Praza goto cleanup; 6645*1f6eb021SLiane Praza } else { 6646*1f6eb021SLiane Praza assert(0); 6647*1f6eb021SLiane Praza abort(); 6648*1f6eb021SLiane Praza } 6649*1f6eb021SLiane Praza } 6650*1f6eb021SLiane Praza 6651*1f6eb021SLiane Praza scf_tmpl_pg_reset(t); 6652*1f6eb021SLiane Praza 6653*1f6eb021SLiane Praza /* 6654*1f6eb021SLiane Praza * Confirm required property groups are present. 6655*1f6eb021SLiane Praza */ 6656*1f6eb021SLiane Praza while ((r = scf_tmpl_iter_pgs(t, fmri, snapshot, NULL, 6657*1f6eb021SLiane Praza SCF_PG_TMPL_FLAG_REQUIRED)) == 1) { 6658*1f6eb021SLiane Praza free(pg_name); 6659*1f6eb021SLiane Praza free(type); 6660*1f6eb021SLiane Praza 6661*1f6eb021SLiane Praza if (scf_tmpl_pg_name(t, &pg_name) == -1) 6662*1f6eb021SLiane Praza goto cleanup; 6663*1f6eb021SLiane Praza if (scf_tmpl_pg_type(t, &type) == -1) 6664*1f6eb021SLiane Praza goto cleanup; 6665*1f6eb021SLiane Praza /* 6666*1f6eb021SLiane Praza * required property group templates should not have 6667*1f6eb021SLiane Praza * wildcarded name or type 6668*1f6eb021SLiane Praza */ 6669*1f6eb021SLiane Praza if (strcmp(pg_name, SCF_TMPL_WILDCARD) == 0 || 6670*1f6eb021SLiane Praza strcmp(type, SCF_TMPL_WILDCARD) == 0) { 6671*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID); 6672*1f6eb021SLiane Praza goto cleanup; 6673*1f6eb021SLiane Praza } 6674*1f6eb021SLiane Praza 6675*1f6eb021SLiane Praza if (_get_pg(NULL, inst, snap, pg_name, pg) != 0) { 6676*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6677*1f6eb021SLiane Praza goto cleanup; 6678*1f6eb021SLiane Praza } else switch (scf_error()) { 6679*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6680*1f6eb021SLiane Praza if (_add_tmpl_missing_pg_error(*errs, t) == -1) 6681*1f6eb021SLiane Praza goto cleanup; 6682*1f6eb021SLiane Praza continue; 6683*1f6eb021SLiane Praza 6684*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6685*1f6eb021SLiane Praza case SCF_ERROR_HANDLE_MISMATCH: 6686*1f6eb021SLiane Praza case SCF_ERROR_NOT_SET: 6687*1f6eb021SLiane Praza default: 6688*1f6eb021SLiane Praza assert(0); 6689*1f6eb021SLiane Praza abort(); 6690*1f6eb021SLiane Praza } 6691*1f6eb021SLiane Praza } 6692*1f6eb021SLiane Praza } 6693*1f6eb021SLiane Praza if (r < 0) { 6694*1f6eb021SLiane Praza if (ismember(scf_error(), errors_server)) { 6695*1f6eb021SLiane Praza goto cleanup; 6696*1f6eb021SLiane Praza } else switch (scf_error()) { 6697*1f6eb021SLiane Praza case SCF_ERROR_NOT_FOUND: 6698*1f6eb021SLiane Praza break; 6699*1f6eb021SLiane Praza 6700*1f6eb021SLiane Praza case SCF_ERROR_INVALID_ARGUMENT: 6701*1f6eb021SLiane Praza goto cleanup; 6702*1f6eb021SLiane Praza 6703*1f6eb021SLiane Praza default: 6704*1f6eb021SLiane Praza assert(0); 6705*1f6eb021SLiane Praza abort(); 6706*1f6eb021SLiane Praza } 6707*1f6eb021SLiane Praza } 6708*1f6eb021SLiane Praza 6709*1f6eb021SLiane Praza ret = 0; 6710*1f6eb021SLiane Praza if ((*errs)->tes_num_errs > 0) 6711*1f6eb021SLiane Praza ret = 1; 6712*1f6eb021SLiane Praza cleanup: 6713*1f6eb021SLiane Praza if (ret != 1) { 6714*1f6eb021SLiane Praza /* there are no errors to report */ 6715*1f6eb021SLiane Praza scf_tmpl_errors_destroy(*errs); 6716*1f6eb021SLiane Praza *errs = NULL; 6717*1f6eb021SLiane Praza } 6718*1f6eb021SLiane Praza scf_tmpl_pg_destroy(t); 6719*1f6eb021SLiane Praza free(type); 6720*1f6eb021SLiane Praza free(pg_name); 6721*1f6eb021SLiane Praza 6722*1f6eb021SLiane Praza scf_iter_destroy(iter); 6723*1f6eb021SLiane Praza scf_pg_destroy(pg); 6724*1f6eb021SLiane Praza scf_instance_destroy(inst); 6725*1f6eb021SLiane Praza scf_snapshot_destroy(snap); 6726*1f6eb021SLiane Praza 6727*1f6eb021SLiane Praza return (ret); 6728*1f6eb021SLiane Praza } 6729*1f6eb021SLiane Praza 6730*1f6eb021SLiane Praza void 6731*1f6eb021SLiane Praza scf_tmpl_errors_destroy(scf_tmpl_errors_t *errs) 6732*1f6eb021SLiane Praza { 6733*1f6eb021SLiane Praza int i; 6734*1f6eb021SLiane Praza scf_tmpl_error_t *e; 6735*1f6eb021SLiane Praza 6736*1f6eb021SLiane Praza if (errs == NULL) 6737*1f6eb021SLiane Praza return; 6738*1f6eb021SLiane Praza 6739*1f6eb021SLiane Praza for (i = 0; i < errs->tes_num_errs; ++i) { 6740*1f6eb021SLiane Praza e = errs->tes_errs[i]; 6741*1f6eb021SLiane Praza if (errs->tes_flag != 0) { 6742*1f6eb021SLiane Praza free((char *)e->te_pg_name); 6743*1f6eb021SLiane Praza free((char *)e->te_prop_name); 6744*1f6eb021SLiane Praza free((char *)e->te_ev1); 6745*1f6eb021SLiane Praza free((char *)e->te_ev2); 6746*1f6eb021SLiane Praza free((char *)e->te_actual); 6747*1f6eb021SLiane Praza free((char *)e->te_tmpl_fmri); 6748*1f6eb021SLiane Praza free((char *)e->te_tmpl_pg_name); 6749*1f6eb021SLiane Praza free((char *)e->te_tmpl_pg_type); 6750*1f6eb021SLiane Praza free((char *)e->te_tmpl_prop_name); 6751*1f6eb021SLiane Praza free((char *)e->te_tmpl_prop_type); 6752*1f6eb021SLiane Praza } 6753*1f6eb021SLiane Praza free(e); 6754*1f6eb021SLiane Praza } 6755*1f6eb021SLiane Praza free((char *)errs->tes_fmri); 6756*1f6eb021SLiane Praza free((char *)errs->tes_prefix); 6757*1f6eb021SLiane Praza free(errs->tes_errs); 6758*1f6eb021SLiane Praza free(errs); 6759*1f6eb021SLiane Praza } 6760*1f6eb021SLiane Praza 6761*1f6eb021SLiane Praza int 6762*1f6eb021SLiane Praza scf_tmpl_error_source_fmri(const scf_tmpl_error_t *err, char **fmri) 6763*1f6eb021SLiane Praza { 6764*1f6eb021SLiane Praza assert(err != NULL); 6765*1f6eb021SLiane Praza switch (err->te_type) { 6766*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6767*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6768*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6769*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6770*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6771*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6772*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6773*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6774*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6775*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6776*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6777*1f6eb021SLiane Praza *fmri = (char *)err->te_tmpl_fmri; 6778*1f6eb021SLiane Praza return (0); 6779*1f6eb021SLiane Praza /*NOTREACHED*/ 6780*1f6eb021SLiane Praza default: 6781*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6782*1f6eb021SLiane Praza } 6783*1f6eb021SLiane Praza return (-1); 6784*1f6eb021SLiane Praza } 6785*1f6eb021SLiane Praza 6786*1f6eb021SLiane Praza int 6787*1f6eb021SLiane Praza scf_tmpl_error_type(const scf_tmpl_error_t *err, scf_tmpl_error_type_t *type) 6788*1f6eb021SLiane Praza { 6789*1f6eb021SLiane Praza assert(err != NULL); 6790*1f6eb021SLiane Praza switch (err->te_type) { 6791*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6792*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6793*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6794*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6795*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6796*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6797*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6798*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6799*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6800*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6801*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6802*1f6eb021SLiane Praza *type = err->te_type; 6803*1f6eb021SLiane Praza return (0); 6804*1f6eb021SLiane Praza /*NOTREACHED*/ 6805*1f6eb021SLiane Praza default: 6806*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6807*1f6eb021SLiane Praza } 6808*1f6eb021SLiane Praza return (-1); 6809*1f6eb021SLiane Praza } 6810*1f6eb021SLiane Praza 6811*1f6eb021SLiane Praza int 6812*1f6eb021SLiane Praza scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t *err, char **name, char **type) 6813*1f6eb021SLiane Praza { 6814*1f6eb021SLiane Praza assert(err != NULL); 6815*1f6eb021SLiane Praza switch (err->te_type) { 6816*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6817*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6818*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6819*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6820*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6821*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6822*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6823*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6824*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6825*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6826*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6827*1f6eb021SLiane Praza if (err->te_tmpl_pg_name != NULL && 6828*1f6eb021SLiane Praza err->te_tmpl_pg_type != NULL) { 6829*1f6eb021SLiane Praza if (name != NULL) 6830*1f6eb021SLiane Praza *name = (char *)err->te_tmpl_pg_name; 6831*1f6eb021SLiane Praza if (type != NULL) 6832*1f6eb021SLiane Praza *type = (char *)err->te_tmpl_pg_type; 6833*1f6eb021SLiane Praza return (0); 6834*1f6eb021SLiane Praza } 6835*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6836*1f6eb021SLiane Praza break; 6837*1f6eb021SLiane Praza default: 6838*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6839*1f6eb021SLiane Praza } 6840*1f6eb021SLiane Praza return (-1); 6841*1f6eb021SLiane Praza } 6842*1f6eb021SLiane Praza 6843*1f6eb021SLiane Praza int 6844*1f6eb021SLiane Praza scf_tmpl_error_pg(const scf_tmpl_error_t *err, char **name, char **type) 6845*1f6eb021SLiane Praza { 6846*1f6eb021SLiane Praza assert(err != NULL); 6847*1f6eb021SLiane Praza switch (err->te_type) { 6848*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6849*1f6eb021SLiane Praza if (err->te_pg_name != NULL && 6850*1f6eb021SLiane Praza err->te_actual != NULL) { 6851*1f6eb021SLiane Praza if (name != NULL) 6852*1f6eb021SLiane Praza *name = (char *)err->te_pg_name; 6853*1f6eb021SLiane Praza if (type != NULL) 6854*1f6eb021SLiane Praza *type = (char *)err->te_actual; 6855*1f6eb021SLiane Praza return (0); 6856*1f6eb021SLiane Praza } 6857*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6858*1f6eb021SLiane Praza break; 6859*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6860*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6861*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6862*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6863*1f6eb021SLiane Praza if (err->te_pg_name != NULL && 6864*1f6eb021SLiane Praza err->te_tmpl_pg_type != NULL) { 6865*1f6eb021SLiane Praza if (name != NULL) 6866*1f6eb021SLiane Praza *name = (char *)err->te_pg_name; 6867*1f6eb021SLiane Praza if (type != NULL) 6868*1f6eb021SLiane Praza *type = (char *)err->te_tmpl_pg_type; 6869*1f6eb021SLiane Praza return (0); 6870*1f6eb021SLiane Praza } 6871*1f6eb021SLiane Praza /*FALLTHROUGH*/ 6872*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6873*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6874*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6875*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6876*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6877*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6878*1f6eb021SLiane Praza break; 6879*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6880*1f6eb021SLiane Praza if (err->te_ev1 != NULL && err->te_ev2 != NULL) { 6881*1f6eb021SLiane Praza if (name != NULL) 6882*1f6eb021SLiane Praza *name = (char *)err->te_ev1; 6883*1f6eb021SLiane Praza if (type != NULL) 6884*1f6eb021SLiane Praza *type = (char *)err->te_ev2; 6885*1f6eb021SLiane Praza return (0); 6886*1f6eb021SLiane Praza } 6887*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6888*1f6eb021SLiane Praza break; 6889*1f6eb021SLiane Praza default: 6890*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6891*1f6eb021SLiane Praza } 6892*1f6eb021SLiane Praza return (-1); 6893*1f6eb021SLiane Praza } 6894*1f6eb021SLiane Praza 6895*1f6eb021SLiane Praza int 6896*1f6eb021SLiane Praza scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t *err, char **name, char **type) 6897*1f6eb021SLiane Praza { 6898*1f6eb021SLiane Praza assert(err != NULL); 6899*1f6eb021SLiane Praza switch (err->te_type) { 6900*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6901*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6902*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6903*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6904*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6905*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6906*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6907*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6908*1f6eb021SLiane Praza if (err->te_tmpl_prop_name != NULL && 6909*1f6eb021SLiane Praza err->te_tmpl_prop_type != NULL) { 6910*1f6eb021SLiane Praza if (name != NULL) 6911*1f6eb021SLiane Praza *name = (char *)err->te_tmpl_prop_name; 6912*1f6eb021SLiane Praza if (type != NULL) 6913*1f6eb021SLiane Praza *type = (char *)err->te_tmpl_prop_type; 6914*1f6eb021SLiane Praza return (0); 6915*1f6eb021SLiane Praza } 6916*1f6eb021SLiane Praza /*FALLTHROUGH*/ 6917*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6918*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6919*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6920*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6921*1f6eb021SLiane Praza break; 6922*1f6eb021SLiane Praza default: 6923*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6924*1f6eb021SLiane Praza } 6925*1f6eb021SLiane Praza return (-1); 6926*1f6eb021SLiane Praza } 6927*1f6eb021SLiane Praza 6928*1f6eb021SLiane Praza int 6929*1f6eb021SLiane Praza scf_tmpl_error_prop(const scf_tmpl_error_t *err, char **name, char **type) 6930*1f6eb021SLiane Praza { 6931*1f6eb021SLiane Praza assert(err != NULL); 6932*1f6eb021SLiane Praza switch (err->te_type) { 6933*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6934*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6935*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6936*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6937*1f6eb021SLiane Praza if (err->te_prop_name != NULL && 6938*1f6eb021SLiane Praza err->te_tmpl_prop_type != NULL) { 6939*1f6eb021SLiane Praza if (name != NULL) 6940*1f6eb021SLiane Praza *name = (char *)err->te_prop_name; 6941*1f6eb021SLiane Praza if (type != NULL) 6942*1f6eb021SLiane Praza *type = (char *)err->te_tmpl_prop_type; 6943*1f6eb021SLiane Praza return (0); 6944*1f6eb021SLiane Praza } 6945*1f6eb021SLiane Praza /*FALLTHROUGH*/ 6946*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6947*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6948*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6949*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6950*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6951*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6952*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6953*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6954*1f6eb021SLiane Praza break; 6955*1f6eb021SLiane Praza default: 6956*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6957*1f6eb021SLiane Praza } 6958*1f6eb021SLiane Praza return (-1); 6959*1f6eb021SLiane Praza } 6960*1f6eb021SLiane Praza 6961*1f6eb021SLiane Praza int 6962*1f6eb021SLiane Praza scf_tmpl_error_value(const scf_tmpl_error_t *err, char **val) 6963*1f6eb021SLiane Praza { 6964*1f6eb021SLiane Praza assert(err != NULL); 6965*1f6eb021SLiane Praza switch (err->te_type) { 6966*1f6eb021SLiane Praza case SCF_TERR_VALUE_CONSTRAINT_VIOLATED: 6967*1f6eb021SLiane Praza case SCF_TERR_RANGE_VIOLATION: 6968*1f6eb021SLiane Praza case SCF_TERR_VALUE_OUT_OF_RANGE: 6969*1f6eb021SLiane Praza case SCF_TERR_INVALID_VALUE: 6970*1f6eb021SLiane Praza if (err->te_actual != NULL) { 6971*1f6eb021SLiane Praza if (val != NULL) 6972*1f6eb021SLiane Praza *val = (char *)err->te_actual; 6973*1f6eb021SLiane Praza return (0); 6974*1f6eb021SLiane Praza } 6975*1f6eb021SLiane Praza /*FALLTHROUGH*/ 6976*1f6eb021SLiane Praza case SCF_TERR_MISSING_PG: 6977*1f6eb021SLiane Praza case SCF_TERR_WRONG_PG_TYPE: 6978*1f6eb021SLiane Praza case SCF_TERR_MISSING_PROP: 6979*1f6eb021SLiane Praza case SCF_TERR_WRONG_PROP_TYPE: 6980*1f6eb021SLiane Praza case SCF_TERR_CARDINALITY_VIOLATION: 6981*1f6eb021SLiane Praza case SCF_TERR_PROP_TYPE_MISMATCH: 6982*1f6eb021SLiane Praza case SCF_TERR_PG_REDEFINE: 6983*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_NOT_FOUND); 6984*1f6eb021SLiane Praza break; 6985*1f6eb021SLiane Praza default: 6986*1f6eb021SLiane Praza (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 6987*1f6eb021SLiane Praza } 6988*1f6eb021SLiane Praza return (-1); 6989*1f6eb021SLiane Praza } 6990*1f6eb021SLiane Praza 6991*1f6eb021SLiane Praza const char * 6992*1f6eb021SLiane Praza scf_tmpl_visibility_to_string(uint8_t vis) 6993*1f6eb021SLiane Praza { 6994*1f6eb021SLiane Praza if (vis == SCF_TMPL_VISIBILITY_READONLY) 6995*1f6eb021SLiane Praza return (SCF_TM_VISIBILITY_READONLY); 6996*1f6eb021SLiane Praza else if (vis == SCF_TMPL_VISIBILITY_HIDDEN) 6997*1f6eb021SLiane Praza return (SCF_TM_VISIBILITY_HIDDEN); 6998*1f6eb021SLiane Praza else if (vis == SCF_TMPL_VISIBILITY_READWRITE) 6999*1f6eb021SLiane Praza return (SCF_TM_VISIBILITY_READWRITE); 7000*1f6eb021SLiane Praza else 7001*1f6eb021SLiane Praza return ("unknown"); 7002*1f6eb021SLiane Praza } 7003