4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
29 * This file implements the bulk of the libscf templates interfaces.
30 * Templates describe metadata about a service or instance in general,
31 * and individual configuration properties on those services and instances.
32 * Human-consumable descriptions can be provided, along with definitions
33 * of valid configuration. See service_bundle.dtd.1 for XML definitions
34 * of templates, and the svccfg code for information on how those definitions
35 * are translated into the repository.
37 * The main data structures are scf_pg_tmpl and scf_prop_tmpl. These
38 * are allocated by the callers through scf_tmpl_[pg|prop]_create(), and
39 * destroyed with scf_tmpl_[pg|prop]_destroy(). They are populated by
40 * scf_tmpl_get_by_pg_name(), scf_tmpl_get_by_pg(), and
41 * scf_tmpl_get_by_prop(). They also store the iterator state for
42 * scf_tmpl_iter_pgs() and scf_tmpl_iter_props().
44 * These data structures are then consumed by other functions to
45 * gather information about the template (e.g. name, description,
46 * choices, constraints, etc.).
48 * scf_tmpl_validate_fmri() does instance validation against template
49 * data, and populates a set of template errors which can be explored using
50 * the scf_tmpl_next_error() and the scf_tmpl_error*() suite of functions.
52 * The main data structures for template errors are scf_tmpl_errors,
53 * defined in this file, and scf_tmpl_error, defined in libscf_priv.h.
54 * scf_tmpl_error is shared with svccfg to offer common printing
55 * of error messages between libscf and svccfg.
57 * General convenience functions are towards the top of this file,
58 * followed by pg and prop template discovery functions, followed
59 * by functions which gather information about the discovered
60 * template. Validation and error functions are at the end of this file.
63 #include "lowlevel_impl.h"
64 #include "libscf_impl.h"
75 #define SCF_TMPL_PG_COMMON_NAME_C "common_name_C"
77 #define SCF__TMPL_ITER_NONE 0
78 #define SCF__TMPL_ITER_INST 1
79 #define SCF__TMPL_ITER_RESTARTER 2
80 #define SCF__TMPL_ITER_GLOBAL 3
82 #define SCF_TMPL_PG_NT 0
83 #define SCF_TMPL_PG_N 1
84 #define SCF_TMPL_PG_T 2
85 #define SCF_TMPL_PG_WILD 3
90 scf_propertygroup_t
*pt_pg
;
91 scf_service_t
*pt_orig_svc
;
92 scf_service_t
*pt_svc
;
93 scf_instance_t
*pt_orig_inst
;
94 scf_instance_t
*pt_inst
;
95 scf_snapshot_t
*pt_snap
;
101 #define SCF_WALK_ERROR -1
102 #define SCF_WALK_NEXT 0
103 #define SCF_WALK_DONE 1
105 struct pg_tmpl_walk
{
106 const char *pw_snapname
;
107 const char *pw_pgname
;
108 const char *pw_pgtype
;
109 scf_instance_t
*pw_inst
;
110 scf_service_t
*pw_svc
;
111 scf_snapshot_t
*pw_snap
;
112 scf_propertygroup_t
*pw_pg
;
113 const char *pw_target
;
114 char *pw_tmpl_pgname
;
117 typedef struct pg_tmpl_walk pg_tmpl_walk_t
;
119 typedef int walk_template_inst_func_t(scf_service_t
*_svc
,
120 scf_instance_t
*_inst
, pg_tmpl_walk_t
*p
);
122 struct scf_prop_tmpl
{
125 scf_pg_tmpl_t
*prt_t
;
126 scf_propertygroup_t
*prt_pg
;
128 scf_iter_t
*prt_iter
;
132 * Common server errors are usually passed back to the caller. This
133 * array defines them centrally so that they don't need to be enumerated
134 * in every libscf call.
136 static const scf_error_t errors_server
[] = {
137 SCF_ERROR_BACKEND_ACCESS
,
138 SCF_ERROR_CONNECTION_BROKEN
,
140 SCF_ERROR_HANDLE_DESTROYED
,
143 SCF_ERROR_NO_RESOURCES
,
145 SCF_ERROR_PERMISSION_DENIED
,
152 * Returns 1 if the supplied error is a member of the error array, 0
156 ismember(const scf_error_t error
, const scf_error_t error_array
[])
160 for (i
= 0; error_array
[i
] != 0; ++i
) {
161 if (error
== error_array
[i
])
169 * char *_scf_tmpl_get_fmri()
171 * Given a pg_tmpl, returns the FMRI of the service or instance that
172 * template describes. The allocated string must be freed with free().
174 * On failure, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
175 * _DELETED, or _NO_MEMORY.
178 _scf_tmpl_get_fmri(const scf_pg_tmpl_t
*t
)
180 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
) + 1;
182 char *buf
= malloc(sz
);
184 assert(t
->pt_svc
!= NULL
|| t
->pt_inst
!= NULL
);
185 assert(t
->pt_svc
== NULL
|| t
->pt_inst
== NULL
);
188 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
192 if (t
->pt_inst
!= NULL
)
193 r
= scf_instance_to_fmri(t
->pt_inst
, buf
, sz
);
195 r
= scf_service_to_fmri(t
->pt_svc
, buf
, sz
);
198 if (ismember(scf_error(), errors_server
)) {
211 * char *_scf_get_pg_type()
213 * Given a propertygroup, returns an allocated string containing the
214 * type. The string must be freed with free().
216 * On failure, returns NULL and sets scf_error() to: _CONNECTION_BROKEN,
217 * _DELETED, or _NO_MEMORY.
220 _scf_get_pg_type(scf_propertygroup_t
*pg
)
222 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH
) + 1;
223 char *buf
= malloc(sz
);
226 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
227 } else if (scf_pg_get_type(pg
, buf
, sz
) == -1) {
228 if (ismember(scf_error(), errors_server
)) {
241 * char *_scf_get_prop_name()
243 * Given a property, returns the name in an allocated string. The string must
244 * be freed with free().
246 * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
247 * _DELETED, or _NO_MEMORY.
250 _scf_get_prop_name(scf_property_t
*prop
)
252 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
253 char *buf
= malloc(sz
);
256 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
257 } else if (scf_property_get_name(prop
, buf
, sz
) == -1) {
258 if (ismember(scf_error(), errors_server
)) {
271 * char *_scf_get_prop_type()
273 * Given a property, returns the type in an allocated string. The string must
274 * be freed with free().
276 * On error, returns NULL and sets scf_error() to _CONNECTION_BROKEN,
277 * _DELETED, or _NO_MEMORY.
280 _scf_get_prop_type(scf_property_t
*prop
)
285 if (scf_property_type(prop
, &type
) == -1) {
286 if (ismember(scf_error(), errors_server
)) {
294 ret
= strdup(scf_type_to_string(type
));
296 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
302 * int _read_single_value_from_pg()
304 * Reads a single value from the pg and property name specified. On success,
305 * returns an allocated value that must be freed.
307 * Returns -1 on failure, sets scf_error() to:
308 * SCF_ERROR_BACKEND_ACCESS
309 * SCF_ERROR_CONNECTION_BROKEN
310 * SCF_ERROR_CONSTRAINT_VIOLATED
311 * Property has more than one value associated with it.
313 * SCF_ERROR_HANDLE_DESTROYED
315 * SCF_ERROR_INVALID_ARGUMENT
316 * prop_name not a valid property name.
317 * SCF_ERROR_NO_MEMORY
318 * SCF_ERROR_NO_RESOURCES
319 * SCF_ERROR_NOT_BOUND
320 * SCF_ERROR_NOT_FOUND
321 * Property doesn't exist or exists and has no value.
323 * Property group specified by pg is not set.
324 * SCF_ERROR_PERMISSION_DENIED
327 _read_single_value_from_pg(scf_propertygroup_t
*pg
, const char *prop_name
,
331 scf_property_t
*prop
;
335 if ((h
= scf_pg_handle(pg
)) == NULL
) {
336 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
340 prop
= scf_property_create(h
);
341 *val
= scf_value_create(h
);
343 if (prop
== NULL
|| *val
== NULL
) {
344 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
345 goto read_single_value_from_pg_fail
;
348 if (scf_pg_get_property(pg
, prop_name
, prop
) != 0) {
349 assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
350 goto read_single_value_from_pg_fail
;
353 if (scf_property_get_value(prop
, *val
) == -1) {
354 assert(scf_error() != SCF_ERROR_NOT_SET
);
355 assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
356 goto read_single_value_from_pg_fail
;
359 goto read_single_value_from_pg_done
;
361 read_single_value_from_pg_fail
:
362 scf_value_destroy(*val
);
366 read_single_value_from_pg_done
:
367 scf_property_destroy(prop
);
372 * char *_scf_read_single_astring_from_pg()
374 * Reads an astring from the pg and property name specified. On success,
375 * returns an allocated string. The string must be freed with free().
377 * Returns NULL on failure, sets scf_error() to:
378 * SCF_ERROR_BACKEND_ACCESS
379 * SCF_ERROR_CONNECTION_BROKEN
380 * SCF_ERROR_CONSTRAINT_VIOLATED
381 * Property has more than one value associated with it.
383 * SCF_ERROR_HANDLE_DESTROYED
385 * SCF_ERROR_INVALID_ARGUMENT
386 * prop_name not a valid property name.
387 * SCF_ERROR_NO_MEMORY
388 * SCF_ERROR_NO_RESOURCES
389 * SCF_ERROR_NOT_BOUND
390 * SCF_ERROR_NOT_FOUND
391 * Property doesn't exist or exists and has no value.
393 * The property group specified by pg is not set.
394 * SCF_ERROR_PERMISSION_DENIED
395 * SCF_ERROR_TYPE_MISMATCH
398 _scf_read_single_astring_from_pg(scf_propertygroup_t
*pg
, const char *prop_name
)
402 ssize_t rsize
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
405 if (_read_single_value_from_pg(pg
, prop_name
, &val
) == -1)
410 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
414 if (scf_value_get_astring(val
, ret
, rsize
) < 0) {
415 assert(scf_error() != SCF_ERROR_NOT_SET
);
421 scf_value_destroy(val
);
426 * char *_scf_read_tmpl_prop_type_as_string()
428 * Reads the property type and returns it as an allocated string. The string
429 * must be freed with free().
431 * Returns NULL on failure, sets scf_error() to _BACKEND_ACCESS,
432 * _CONNECTION_BROKEN, _DELETED, _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY,
433 * _NO_RESOURCES, _NOT_BOUND, _PERMISSION_DENIED, or _TEMPLATE_INVALID.
436 _scf_read_tmpl_prop_type_as_string(const scf_prop_tmpl_t
*pt
)
440 type
= _scf_read_single_astring_from_pg(pt
->prt_pg
,
441 SCF_PROPERTY_TM_TYPE
);
443 if (ismember(scf_error(), errors_server
)) {
445 } else switch (scf_error()) {
446 case SCF_ERROR_CONSTRAINT_VIOLATED
:
447 case SCF_ERROR_NOT_FOUND
:
448 case SCF_ERROR_TYPE_MISMATCH
:
449 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
452 case SCF_ERROR_INVALID_ARGUMENT
:
453 case SCF_ERROR_NOT_SET
:
464 * int _read_single_boolean_from_pg()
466 * Reads a boolean from the pg and property name specified.
468 * Returns -1 on failure, sets scf_error() to:
469 * SCF_ERROR_BACKEND_ACCESS
470 * SCF_ERROR_CONNECTION_BROKEN
471 * SCF_ERROR_CONSTRAINT_VIOLATED
472 * Property has more than one value associated with it.
474 * SCF_ERROR_HANDLE_DESTROYED
476 * SCF_ERROR_INVALID_ARGUMENT
477 * prop_name is not a valid property name.
478 * SCF_ERROR_NO_MEMORY
479 * SCF_ERROR_NO_RESOURCES
480 * SCF_ERROR_NOT_BOUND
481 * SCF_ERROR_NOT_FOUND
482 * Property doesn't exist or exists and has no value.
484 * The property group specified by pg is not set.
485 * SCF_ERROR_PERMISSION_DENIED
486 * SCF_ERROR_TYPE_MISMATCH
489 _read_single_boolean_from_pg(scf_propertygroup_t
*pg
, const char *prop_name
,
495 if (_read_single_value_from_pg(pg
, prop_name
, &val
) == -1)
498 if (scf_value_get_boolean(val
, bool) < 0) {
499 assert(scf_error() != SCF_ERROR_NOT_SET
);
503 scf_value_destroy(val
);
508 * static char ** _append_astrings_values()
510 * This function reads the values from the property prop_name in pg and
511 * appends to an existing scf_values_t *vals. vals may be empty, but
512 * must exist. The function skips over zero-length and duplicate values.
514 * Returns NULL on failure, sets scf_error() to:
515 * SCF_ERROR_BACKEND_ACCESS
516 * SCF_ERROR_CONNECTION_BROKEN
518 * SCF_ERROR_HANDLE_DESTROYED
520 * SCF_ERROR_INVALID_ARGUMENT
521 * prop_name is not a valid property name.
522 * SCF_ERROR_NO_MEMORY
523 * SCF_ERROR_NO_RESOURCES
524 * SCF_ERROR_NOT_BOUND
525 * SCF_ERROR_NOT_FOUND
527 * SCF_ERROR_PERMISSION_DENIED
528 * SCF_ERROR_TYPE_MISMATCH
531 _append_astrings_values(scf_propertygroup_t
*pg
, const char *prop_name
,
535 scf_property_t
*prop
;
538 ssize_t rsize
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
539 int err
, count
, cursz
, i
;
541 assert(vals
!= NULL
);
542 assert(vals
->value_type
== SCF_TYPE_ASTRING
);
543 assert(vals
->reserved
== NULL
);
544 count
= vals
->value_count
;
547 vals
->values
.v_astring
= calloc(cursz
, sizeof (char *));
548 if (vals
->values
.v_astring
== NULL
) {
549 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
554 * The array may be bigger, but it is irrelevant since
555 * we will always re-allocate a new one.
560 if ((h
= scf_pg_handle(pg
)) == NULL
) {
561 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
565 prop
= scf_property_create(h
);
566 val
= scf_value_create(h
);
567 iter
= scf_iter_create(h
);
569 if (prop
== NULL
|| val
== NULL
|| iter
== NULL
) {
570 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
571 goto append_single_astring_from_pg_fail
;
574 if (scf_pg_get_property(pg
, prop_name
, prop
) != 0) {
575 assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
576 goto append_single_astring_from_pg_fail
;
579 if (scf_iter_property_values(iter
, prop
) != 0) {
580 assert(scf_error() != SCF_ERROR_NOT_SET
);
581 assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
582 goto append_single_astring_from_pg_fail
;
585 while ((err
= scf_iter_next_value(iter
, val
)) == 1) {
589 if (count
+ 1 >= cursz
) {
593 if ((aux
= calloc(cursz
, sizeof (char *))) == NULL
) {
594 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
595 goto append_single_astring_from_pg_fail
;
597 (void) memcpy(aux
, vals
->values
.v_astring
,
598 count
* sizeof (char *));
599 free(vals
->values
.v_astring
);
600 vals
->values
.v_astring
= aux
;
603 vals
->values
.v_astring
[count
] = malloc(rsize
);
604 if (vals
->values
.v_astring
[count
] == NULL
) {
605 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
606 goto append_single_astring_from_pg_fail
;
609 if ((r
= scf_value_get_astring(val
,
610 vals
->values
.v_astring
[count
], rsize
)) <= 0) {
611 /* discard zero length strings */
613 free(vals
->values
.v_astring
[count
]);
616 assert(scf_error() != SCF_ERROR_NOT_SET
);
617 goto append_single_astring_from_pg_fail
;
619 for (i
= 0, flag
= 0; i
< count
; ++i
) {
620 /* find and discard duplicates */
621 if (strncmp(vals
->values
.v_astring
[i
],
622 vals
->values
.v_astring
[count
], rsize
) == 0) {
623 free(vals
->values
.v_astring
[count
]);
634 vals
->value_count
= count
;
637 assert(scf_error() != SCF_ERROR_NOT_SET
);
638 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
639 assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
640 goto append_single_astring_from_pg_fail
;
642 vals
->values_as_strings
= vals
->values
.v_astring
;
645 goto append_single_astring_from_pg_done
;
647 append_single_astring_from_pg_fail
:
648 for (i
= 0; i
<= count
; ++i
) {
649 free(vals
->values
.v_astring
[i
]);
650 vals
->values
.v_astring
[i
] = NULL
;
652 free(vals
->values
.v_astring
);
653 vals
->values
.v_astring
= NULL
;
654 vals
->value_count
= 0;
656 append_single_astring_from_pg_done
:
657 scf_iter_destroy(iter
);
658 scf_property_destroy(prop
);
659 scf_value_destroy(val
);
660 return (vals
->values
.v_astring
);
664 * Returns NULL on failure, sets scf_error() to:
665 * SCF_ERROR_BACKEND_ACCESS
666 * SCF_ERROR_CONNECTION_BROKEN
668 * SCF_ERROR_HANDLE_DESTROYED
670 * SCF_ERROR_INVALID_ARGUMENT
671 * prop_name is not a valid property name.
672 * SCF_ERROR_NO_MEMORY
673 * SCF_ERROR_NO_RESOURCES
674 * SCF_ERROR_NOT_BOUND
675 * SCF_ERROR_NOT_FOUND
677 * SCF_ERROR_PERMISSION_DENIED
678 * SCF_ERROR_TYPE_MISMATCH
681 _read_astrings_values(scf_propertygroup_t
*pg
, const char *prop_name
,
684 assert(vals
!= NULL
);
685 vals
->value_count
= 0;
686 vals
->value_type
= SCF_TYPE_ASTRING
;
687 vals
->reserved
= NULL
;
688 return (_append_astrings_values(pg
, prop_name
, vals
));
692 _scf_sanitize_locale(char *locale
)
694 for (; *locale
!= '\0'; locale
++)
695 if (!isalnum(*locale
) && *locale
!= '_')
700 * The returned string needs to be freed by the caller
701 * Returns NULL on failure. Sets scf_error() to:
702 * SCF_ERROR_NO_MEMORY
703 * SCF_ERROR_INVALID_ARGUMENT
704 * Name isn't short enough to add the locale to.
707 _add_locale_to_name(const char *name
, const char *locale
)
714 locale
= setlocale(LC_MESSAGES
, NULL
);
715 loc
= strdup(locale
);
717 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
720 _scf_sanitize_locale(loc
);
723 lsz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
726 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
730 (void) strlcpy(lname
, name
, lsz
);
731 if (strlcat(lname
, loc
, lsz
) >= lsz
) {
732 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
743 * char *_tmpl_pg_name(pg, type, use_type)
745 * pg and type can both be NULL. Returns the name of the most specific
746 * template property group name based on the inputs.
747 * If use_type is set and pg is not NULL, a property group name for a
748 * property group template that has type defined is returned, even if no
751 * Returns NULL on failure and sets scf_error() to:
752 * SCF_ERROR_INVALID_ARGUMENT
753 * can't combine the arguments and get a reasonable length name
754 * SCF_ERROR_NO_MEMORY
758 _tmpl_pg_name(const char *pg
, const char *type
, int use_type
)
761 ssize_t limit
, size
= 0;
763 limit
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
764 name
= malloc(limit
);
766 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
770 if (pg
== NULL
&& type
== NULL
) {
771 if (strlcpy(name
, SCF_PG_TM_PG_PATTERN_PREFIX
, limit
) >=
777 } else if (pg
!= NULL
&& type
!= NULL
) {
778 size
= snprintf(name
, limit
, "%s%s",
779 SCF_PG_TM_PG_PATTERN_NT_PREFIX
, pg
);
780 } else if (pg
!= NULL
&& type
== NULL
&& use_type
== 1) {
781 size
= snprintf(name
, limit
, "%s%s",
782 SCF_PG_TM_PG_PATTERN_NT_PREFIX
, pg
);
783 } else if (pg
!= NULL
&& type
== NULL
) {
784 size
= snprintf(name
, limit
, "%s%s",
785 SCF_PG_TM_PG_PATTERN_N_PREFIX
, pg
);
786 } else if (type
!= NULL
&& pg
== NULL
) {
787 size
= snprintf(name
, limit
, "%s%s",
788 SCF_PG_TM_PG_PATTERN_T_PREFIX
, type
);
795 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
805 * Gets the name of the supplied property group. On success, returns an
806 * allocated string. The string must be freed by free().
808 * Returns NULL on failure and sets scf_error() to _CONNECTION_BROKEN,
809 * _DELETED, or _NO_MEMORY.
812 _scf_get_pg_name(scf_propertygroup_t
*pg
)
814 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
815 char *buf
= malloc(sz
);
818 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
819 } else if (scf_pg_get_name(pg
, buf
, sz
) == -1) {
820 if (ismember(scf_error(), errors_server
)) {
833 * char *_tmpl_prop_name()
835 * Returns the name of the property template prop (which is the name of
836 * the property template property group) in the property group
837 * template t. Returns NULL on failure and sets scf_error() to:
838 * SCF_ERROR_CONNECTION_BROKEN
840 * SCF_ERROR_INVALID_ARGUMENT
841 * can't combine the arguments and get a reasonable length name
842 * SCF_ERROR_NO_MEMORY
845 _tmpl_prop_name(const char *prop
, scf_pg_tmpl_t
*t
)
847 char *name
= NULL
, *pg_name
= NULL
;
849 ssize_t limit
, size
= 0;
851 assert(prop
!= NULL
);
852 assert(t
->pt_pg
!= NULL
);
854 limit
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
855 name
= malloc(limit
);
857 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
861 if ((pg_name
= _scf_get_pg_name(t
->pt_pg
)) == NULL
) {
866 prefix_size
= strlen(SCF_PG_TM_PG_PAT_BASE
);
867 if (strncmp(pg_name
, SCF_PG_TM_PG_PAT_BASE
, prefix_size
) != 0) {
868 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
874 size
= snprintf(name
, limit
, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX
,
875 pg_name
+ prefix_size
, prop
);
878 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
889 * int _get_snapshot()
891 * Gets the specified snapshot. If "snapshot" isn't defined, use the
892 * running snapshot. If the snapshot isn't found, that may or may
893 * not be an error depending on the caller. Return 0 in that case,
894 * but leave scf_error() set to SCF_ERROR_NOT_FOUND. On all other
895 * errors, set scf_error() to:
896 * SCF_ERROR_BACKEND_ACCESS
897 * SCF_ERROR_CONNECTION_BROKEN
899 * SCF_ERR_HANDLE_DESTROYED
901 * SCF_ERROR_INVALID_ARGUMENT
902 * The handle argument is NULL, or snaphot is not a valid snapshot name
903 * SCF_ERROR_NO_MEMORY
904 * SCF_ERROR_NO_RESOURCES
905 * SCF_ERROR_NOT_BOUND
906 * SCF_ERROR_NOT_FOUND
909 _get_snapshot(scf_instance_t
*inst
, const char *snapshot
,
910 scf_snapshot_t
**snap
)
915 h
= scf_instance_handle(inst
);
921 if ((*snap
= scf_snapshot_create(h
)) == NULL
) {
925 /* Use running snapshot by default. */
926 if (snapshot
== NULL
)
927 err
= scf_instance_get_snapshot(inst
, "running", *snap
);
929 err
= scf_instance_get_snapshot(inst
, snapshot
, *snap
);
932 if (ismember(scf_error(), errors_server
)) {
933 scf_snapshot_destroy(*snap
);
936 } else switch (scf_error()) {
937 case SCF_ERROR_INVALID_ARGUMENT
:
938 scf_snapshot_destroy(*snap
);
942 case SCF_ERROR_NOT_FOUND
:
943 scf_snapshot_destroy(*snap
);
947 case SCF_ERROR_NOT_SET
:
948 case SCF_ERROR_HANDLE_MISMATCH
:
956 * Explicitly set SCF_ERROR_NONE so that the SCF_ERROR_NOT_FOUND
957 * return above is explicitly guaranteed to be from
958 * scf_instance_get_snapshot().
960 (void) scf_set_error(SCF_ERROR_NONE
);
965 * Returns NULL on error, sets scf_error() to:
966 * SCF_ERROR_BACKEND_ACCESS
967 * SCF_ERROR_CONNECTION_BROKEN
968 * SCF_ERROR_CONSTRAINT_VIOLATED
969 * The restarter's FMRI does not match an existing instance.
971 * SCF_ERROR_HANDLE_DESTROYED
973 * SCF_ERROR_INVALID_ARGUMENT
974 * The restarter's FMRI is not a valid FMRI.
975 * SCF_ERROR_NO_MEMORY
976 * SCF_ERROR_NO_RESOURCES
977 * SCF_ERROR_NOT_BOUND
978 * SCF_ERROR_NOT_FOUND
979 * Property doesn't exist or exists and has no value.
980 * SCF_ERROR_TEMPLATE_INVALID
981 * restarter property is not SCF_TYPE_ASTRING or has more than one value
983 static scf_instance_t
*
984 _get_restarter_inst(scf_handle_t
*h
, scf_service_t
*svc
,
985 scf_instance_t
*inst
, scf_snapshot_t
*s
)
987 char *restarter
= NULL
;
988 scf_instance_t
*ri
= NULL
;
989 scf_propertygroup_t
*pg
= NULL
;
992 assert(svc
!= NULL
|| inst
!= NULL
);
993 assert(svc
== NULL
|| inst
== NULL
);
995 if ((ri
= scf_instance_create(h
)) == NULL
||
996 (pg
= scf_pg_create(h
)) == NULL
) {
997 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
998 goto _get_restarter_inst_fail
;
1002 ret
= scf_instance_get_pg_composed(inst
, s
, SCF_PG_GENERAL
,
1005 ret
= scf_service_get_pg(svc
, SCF_PG_GENERAL
, pg
);
1008 if (ismember(scf_error(), errors_server
)) {
1009 goto _get_restarter_inst_fail
;
1010 } else switch (scf_error()) {
1011 case SCF_ERROR_NOT_FOUND
:
1012 /* Assume default restarter. */
1015 case SCF_ERROR_NOT_SET
:
1016 case SCF_ERROR_HANDLE_MISMATCH
:
1018 * If the arguments to the above functions
1019 * aren't derived from the same handle, there's
1020 * something wrong with the internal implementation,
1021 * not the public caller further up the chain.
1023 case SCF_ERROR_INVALID_ARGUMENT
:
1029 restarter
= _scf_read_single_astring_from_pg(pg
,
1030 SCF_PROPERTY_RESTARTER
);
1031 /* zero length string is NOT a valid restarter */
1032 if (restarter
!= NULL
&& restarter
[0] == '\0') {
1035 } else if (restarter
== NULL
) {
1036 if (ismember(scf_error(), errors_server
)) {
1037 goto _get_restarter_inst_fail
;
1038 } else switch (scf_error()) {
1039 case SCF_ERROR_NOT_FOUND
:
1042 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1043 case SCF_ERROR_TYPE_MISMATCH
:
1044 (void) scf_set_error(
1045 SCF_ERROR_TEMPLATE_INVALID
);
1046 goto _get_restarter_inst_fail
;
1048 case SCF_ERROR_NOT_SET
:
1049 case SCF_ERROR_INVALID_ARGUMENT
:
1057 if (restarter
== NULL
) {
1058 /* Use default restarter */
1059 restarter
= strdup(SCF_SERVICE_STARTD
);
1060 if (restarter
== NULL
) {
1061 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1062 goto _get_restarter_inst_fail
;
1066 if (scf_handle_decode_fmri(h
, restarter
, NULL
, NULL
, ri
, NULL
, NULL
,
1067 SCF_DECODE_FMRI_EXACT
|SCF_DECODE_FMRI_REQUIRE_INSTANCE
) != 0) {
1068 if (ismember(scf_error(), errors_server
)) {
1069 goto _get_restarter_inst_fail
;
1070 } else switch (scf_error()) {
1071 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1072 case SCF_ERROR_INVALID_ARGUMENT
:
1073 case SCF_ERROR_NOT_FOUND
:
1074 goto _get_restarter_inst_fail
;
1076 case SCF_ERROR_HANDLE_MISMATCH
:
1077 case SCF_ERROR_NOT_SET
:
1088 _get_restarter_inst_fail
:
1090 scf_instance_destroy(ri
);
1096 * Returns NULL on error, sets scf_error() to:
1097 * SCF_ERROR_BACKEND_ACCESS
1098 * SCF_ERROR_CONNECTION_BROKEN
1099 * SCF_ERROR_CONSTRAINT_VIOLATED
1100 * Restarter property has more than one value associated with it,
1101 * or FMRI does not meet restrictions in scf_handle_decode_fmri() flags.
1103 * SCF_ERROR_HANDLE_DESTROYED
1104 * SCF_ERROR_INTERNAL
1105 * SCF_ERROR_INVALID_ARGUMENT
1106 * The fmri argument in scf_handle_decode_fmri() is not a valid FMRI.
1107 * SCF_ERROR_NO_MEMORY
1108 * SCF_ERROR_NO_RESOURCES
1109 * SCF_ERROR_NOT_BOUND
1110 * SCF_ERROR_NOT_FOUND
1111 * Property doesn't exist or exists and has no value.
1113 static scf_instance_t
*
1114 _get_global_inst(scf_handle_t
*h
)
1118 if ((ri
= scf_instance_create(h
)) == NULL
) {
1119 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
1120 (void) scf_set_error(SCF_ERROR_NO_RESOURCES
);
1124 if (scf_handle_decode_fmri(h
, SCF_INSTANCE_GLOBAL
, NULL
, NULL
, ri
,
1126 SCF_DECODE_FMRI_EXACT
|SCF_DECODE_FMRI_REQUIRE_INSTANCE
) != 0) {
1127 if (ismember(scf_error(), errors_server
)) {
1128 scf_instance_destroy(ri
);
1130 } else switch (scf_error()) {
1131 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1132 case SCF_ERROR_INVALID_ARGUMENT
:
1133 case SCF_ERROR_NOT_FOUND
:
1134 scf_instance_destroy(ri
);
1137 case SCF_ERROR_HANDLE_MISMATCH
:
1138 case SCF_ERROR_NOT_SET
:
1149 * Call the supplied function for each of the service or instance, the
1150 * service's restarter, and the globally defined template instance.
1151 * If the function returns SCF_WALK_ERROR, the walk is ended. If
1152 * the function returns SCF_WALK_NEXT, the next entity is tried.
1154 * The function is only expected to return SCF_WALK_DONE if it has
1155 * found a property group match in the current entity, and has
1156 * populated p->pw_pg with the matching property group.
1158 * The caller of _walk_template_instances() MUST check if the passed parameters
1159 * inst and svc match the fields pw_inst and pw_svc in the resulting
1160 * pg_tmpl_walk_t and call the destructor for the unmatching objects. The walker
1161 * may silently drop them if the template definition is in the restarter or in
1162 * the global instance.
1165 _walk_template_instances(scf_service_t
*svc
, scf_instance_t
*inst
,
1166 scf_snapshot_t
*snap
, walk_template_inst_func_t
*func
,
1167 pg_tmpl_walk_t
*p
, int flag
)
1169 scf_instance_t
*tmpl_inst
= NULL
;
1174 assert(svc
!= NULL
|| inst
!= NULL
);
1175 assert(svc
== NULL
|| inst
== NULL
);
1178 h
= scf_instance_handle(inst
);
1180 h
= scf_service_handle(svc
);
1184 /* First, use supplied service or instance */
1185 p
->pw_target
= SCF_TM_TARGET_THIS
;
1186 ret
= func(svc
, inst
, p
);
1192 * Check that the template scoping matches and if not,
1195 assert(p
->pw_pg
!= NULL
);
1196 tg
= _scf_read_single_astring_from_pg(p
->pw_pg
,
1197 SCF_PROPERTY_TM_TARGET
);
1198 if (tg
== NULL
|| /* scf_error() was set */
1199 (strcmp(tg
, SCF_TM_TARGET_INSTANCE
) != 0 &&
1200 strcmp(tg
, SCF_TM_TARGET_THIS
) != 0 &&
1201 (flag
& SCF_PG_TMPL_FLAG_EXACT
) !=
1202 SCF_PG_TMPL_FLAG_EXACT
)) {
1203 scf_pg_destroy(p
->pw_pg
);
1212 case SCF_WALK_ERROR
:
1220 /* Next the restarter. */
1221 p
->pw_target
= SCF_TM_TARGET_DELEGATE
;
1222 tmpl_inst
= _get_restarter_inst(h
, svc
, inst
, snap
);
1223 if (tmpl_inst
!= NULL
) {
1224 ret
= func(NULL
, tmpl_inst
, p
);
1230 * Check that the template scoping matches and if not,
1233 assert(p
->pw_pg
!= NULL
);
1234 tg
= _scf_read_single_astring_from_pg(p
->pw_pg
,
1235 SCF_PROPERTY_TM_TARGET
);
1236 if (tg
== NULL
|| /* scf_error() was set */
1237 strcmp(tg
, SCF_TM_TARGET_DELEGATE
) != 0) {
1238 scf_pg_destroy(p
->pw_pg
);
1247 case SCF_WALK_ERROR
:
1256 p
->pw_target
= SCF_TM_TARGET_ALL
;
1257 scf_instance_destroy(tmpl_inst
);
1258 tmpl_inst
= _get_global_inst(h
);
1259 if (tmpl_inst
!= NULL
) {
1260 ret
= func(NULL
, tmpl_inst
, p
);
1266 * Check that the template scoping matches and if not,
1269 assert(p
->pw_pg
!= NULL
);
1270 tg
= _scf_read_single_astring_from_pg(p
->pw_pg
,
1271 SCF_PROPERTY_TM_TARGET
);
1272 if (tg
== NULL
|| /* scf_error() was set */
1273 strcmp(tg
, SCF_TM_TARGET_ALL
) != 0) {
1274 scf_pg_destroy(p
->pw_pg
);
1283 case SCF_WALK_ERROR
:
1294 if (ret
!= SCF_WALK_DONE
)
1295 scf_instance_destroy(tmpl_inst
);
1296 p
->pw_target
= NULL
;
1300 * _get_pg() returns 0 on success and -1 on failure. Sets scf_error()
1302 * SCF_ERROR_BACKEND_ACCESS
1303 * SCF_ERROR_CONNECTION_BROKEN
1305 * SCF_ERROR_HANDLE_MISMATCH
1306 * SCF_ERROR_INTERNAL
1307 * SCF_ERROR_INVALID_ARGUMENT
1308 * name is not a valid property group.
1309 * SCF_ERROR_NO_RESOURCES
1310 * SCF_ERROR_NOT_BOUND
1311 * SCF_ERROR_NOT_FOUND
1315 _get_pg(scf_service_t
*svc
, scf_instance_t
*inst
,
1316 const scf_snapshot_t
*snap
, const char *name
, scf_propertygroup_t
*pg
)
1320 assert(svc
!= NULL
|| inst
!= NULL
);
1321 assert(svc
== NULL
|| inst
== NULL
);
1325 ret
= scf_instance_get_pg_composed(inst
, snap
, name
, pg
);
1327 ret
= scf_service_get_pg(svc
, name
, pg
);
1333 * Returns SCF_WALK_NEXT for not found, SCF_WALK_ERROR for error,
1334 * and SCF_WALK_DONE for found.
1335 * On error, destroy pg and set it to NULL.
1337 * Sets scf_error() if SCF_WALK_ERROR is returned to _BACKEND_ACCESS,
1338 * _CONNECTION_BROKEN, _INTERNAL, _INVALID_ARGUMENT (name is not a
1339 * valid property group), _NO_RESOURCES, or _NOT_BOUND.
1342 _lookup_pg(scf_service_t
*svc
, scf_instance_t
*inst
,
1343 const scf_snapshot_t
*snap
, const char *name
, scf_propertygroup_t
*pg
)
1347 ret
= _get_pg(svc
, inst
, snap
, name
, pg
);
1350 return (SCF_WALK_DONE
);
1352 switch (scf_error()) {
1353 case SCF_ERROR_NOT_FOUND
:
1354 case SCF_ERROR_DELETED
:
1355 return (SCF_WALK_NEXT
);
1357 case SCF_ERROR_BACKEND_ACCESS
:
1358 case SCF_ERROR_CONNECTION_BROKEN
:
1359 case SCF_ERROR_INTERNAL
:
1360 case SCF_ERROR_INVALID_ARGUMENT
:
1361 case SCF_ERROR_NOT_BOUND
:
1362 case SCF_ERROR_NO_RESOURCES
:
1365 return (SCF_WALK_ERROR
);
1367 case SCF_ERROR_NOT_SET
:
1368 case SCF_ERROR_HANDLE_MISMATCH
:
1379 * If match, return 0. If no match, return 1. If error, return -1.
1380 * On error set scf_error() to _BACKEND_ACCESS, _CONNECTION_BROKEN,
1381 * _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, _NO_RESOURCES, _NOT_BOUND,
1382 * _NOT_SET (property group specified by pg is not set), _PERMISSION_DENIED,
1383 * or _TEMPLATE_INVALID (target property is not SCF_TYPE_ASTRING or has
1384 * more than one value).
1387 check_target_match(scf_propertygroup_t
*pg
, const char *target
)
1392 pg_target
= _scf_read_single_astring_from_pg(pg
,
1393 SCF_PROPERTY_TM_TARGET
);
1394 if (pg_target
== NULL
) {
1395 switch (scf_error()) {
1396 case SCF_ERROR_DELETED
:
1397 case SCF_ERROR_NOT_FOUND
:
1400 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1401 case SCF_ERROR_TYPE_MISMATCH
:
1402 (void) scf_set_error(
1403 SCF_ERROR_TEMPLATE_INVALID
);
1406 case SCF_ERROR_BACKEND_ACCESS
:
1407 case SCF_ERROR_CONNECTION_BROKEN
:
1408 case SCF_ERROR_HANDLE_DESTROYED
:
1409 case SCF_ERROR_INTERNAL
:
1410 case SCF_ERROR_NO_RESOURCES
:
1411 case SCF_ERROR_NOT_BOUND
:
1412 case SCF_ERROR_PERMISSION_DENIED
:
1415 case SCF_ERROR_NOT_SET
:
1416 case SCF_ERROR_INVALID_ARGUMENT
:
1424 /* For a desired target of 'this', check for 'this' and 'instance'. */
1425 if ((strcmp(target
, SCF_TM_TARGET_INSTANCE
) == 0 ||
1426 strcmp(target
, SCF_TM_TARGET_THIS
) == 0) &&
1427 (strcmp(pg_target
, SCF_TM_TARGET_INSTANCE
) == 0 ||
1428 strcmp(pg_target
, SCF_TM_TARGET_THIS
) == 0)) {
1432 if (strcmp(target
, SCF_TM_TARGET_DELEGATE
) == 0 &&
1433 strcmp(pg_target
, SCF_TM_TARGET_DELEGATE
) == 0) {
1437 if (strcmp(target
, SCF_TM_TARGET_ALL
) == 0 &&
1438 strcmp(pg_target
, SCF_TM_TARGET_ALL
) == 0) {
1449 * Check if a matching template property group exists for each of:
1450 * name and type, name only, type only, and completely wildcarded
1453 * Both pg_name and pg_type are optional.
1455 * Returns NULL on failure, sets scf_error():
1456 * SCF_ERROR_BACKEND_ACCESS
1457 * SCF_ERROR_CONNECTION_BROKEN
1459 * SCF_ERROR_HANDLE_DESTROYED
1460 * SCF_ERROR_INTERNAL
1461 * SCF_ERROR_INVALID_ARGUMENT
1462 * can't combine the _tmpl_pg_name arguments and get a reasonable
1463 * length name, or pg_name is not a valid property group.
1464 * SCF_ERROR_NO_MEMORY
1465 * SCF_ERROR_NO_RESOURCES
1466 * SCF_ERROR_NOT_BOUND
1467 * SCF_ERROR_NOT_FOUND
1468 * Property doesn't exist or exists and has no value.
1469 * SCF_ERROR_PERMISSION_DENIED
1470 * SCF_ERROR_TEMPLATE_INVALID
1471 * target property is not SCF_TYPE_ASTRING or has more than one value.
1473 static scf_propertygroup_t
*
1474 _find_template_pg_match(scf_service_t
*svc
, scf_instance_t
*inst
,
1475 const scf_snapshot_t
*snap
, const char *pg_name
, const char *pg_type
,
1476 const char *target
, char **tmpl_pg_name
)
1479 scf_propertygroup_t
*pg
= NULL
;
1484 assert(inst
!= NULL
|| svc
!= NULL
);
1485 assert(inst
== NULL
|| svc
== NULL
);
1488 h
= scf_instance_handle(inst
);
1490 h
= scf_service_handle(svc
);
1495 if ((pg
= scf_pg_create(h
)) == NULL
||
1496 (iter
= scf_iter_create(h
)) == NULL
) {
1497 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
1503 * We're going to walk through the possible pg templates that
1504 * could match the supplied name and type. We do this
1505 * by explicit name lookups when possible to avoid having to
1506 * keep track of a most-explicit-match during iteration.
1509 /* First look for a template with name and type set and matching. */
1510 *tmpl_pg_name
= _tmpl_pg_name(pg_name
, pg_type
, 1);
1511 if (*tmpl_pg_name
== NULL
)
1513 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1514 if (ret
!= SCF_WALK_NEXT
) {
1516 if ((r
= check_target_match(pg
, target
)) == 0)
1524 free(*tmpl_pg_name
);
1527 * Need to search on a name-only match before searching on
1531 *tmpl_pg_name
= _tmpl_pg_name(pg_name
, NULL
, 0);
1532 if (*tmpl_pg_name
== NULL
)
1534 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1535 if (ret
!= SCF_WALK_NEXT
) {
1537 if ((r
= check_target_match(pg
, target
)) == 0)
1545 free(*tmpl_pg_name
);
1547 /* Next, see if there's an "nt" template where the type matches. */
1548 if (pg_type
!= NULL
&& pg_name
== NULL
) {
1550 ret
= scf_iter_instance_pgs_typed_composed(iter
, inst
,
1551 snap
, SCF_GROUP_TEMPLATE_PG_PATTERN
);
1553 ret
= scf_iter_service_pgs_typed(iter
, svc
,
1554 SCF_GROUP_TEMPLATE_PG_PATTERN
);
1557 if (ismember(scf_error(), errors_server
)) {
1565 while ((ret
= scf_iter_next_pg(iter
, pg
)) == 1) {
1566 /* Make sure this is a name and type specified pg. */
1567 name
= _scf_read_single_astring_from_pg(pg
,
1568 SCF_PROPERTY_TM_NAME
);
1571 type
= _scf_read_single_astring_from_pg(pg
,
1572 SCF_PROPERTY_TM_TYPE
);
1577 if (strcmp(pg_type
, type
) == 0 &&
1578 check_target_match(pg
, target
) == 0) {
1579 *tmpl_pg_name
= name
;
1587 if (ismember(scf_error(), errors_server
)) {
1596 *tmpl_pg_name
= _tmpl_pg_name(NULL
, pg_type
, 0);
1597 if (*tmpl_pg_name
== NULL
)
1599 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1600 if (ret
!= SCF_WALK_NEXT
) {
1602 if ((r
= check_target_match(pg
, target
)) == 0)
1610 free(*tmpl_pg_name
);
1612 *tmpl_pg_name
= _tmpl_pg_name(NULL
, NULL
, 0);
1613 if (*tmpl_pg_name
== NULL
)
1615 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1616 if (ret
!= SCF_WALK_NEXT
) {
1618 if ((r
= check_target_match(pg
, target
)) == 0)
1627 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
1630 free(*tmpl_pg_name
);
1631 *tmpl_pg_name
= NULL
;
1634 if (ret
== SCF_WALK_ERROR
)
1635 free(*tmpl_pg_name
);
1636 scf_iter_destroy(iter
);
1641 * Finds the pg match in either the supplied service or instance.
1642 * Returns SCF_WALK_ERROR, SCF_WALK_NEXT, or SCF_WALK_DONE.
1643 * If returning SCF_WALK_ERROR, sets scf_error():
1644 * SCF_ERROR_BACKEND_ACCESS
1645 * SCF_ERROR_CONNECTION_BROKEN
1647 * SCF_ERROR_HANDLE_DESTROYED
1648 * SCF_ERROR_INTERNAL
1649 * SCF_ERROR_INVALID_ARGUMENT
1650 * The snaphot is not a valid snapshot name,
1651 * or can't create a reasonable property group template name.
1652 * SCF_ERROR_NO_MEMORY
1653 * SCF_ERROR_NO_RESOURCES
1654 * SCF_ERROR_NOT_BOUND
1655 * SCF_ERROR_NOT_FOUND
1656 * Property doesn't exist or exists and has no value.
1657 * SCF_ERROR_PERMISSION_DENIED
1658 * SCF_ERROR_TEMPLATE_INVALID
1659 * target property is not SCF_TYPE_ASTRING or has more than one value.
1662 find_pg_match(scf_service_t
*svc
, scf_instance_t
*inst
, pg_tmpl_walk_t
*p
)
1664 scf_snapshot_t
*tmpl_snap
= NULL
;
1665 scf_propertygroup_t
*pg
;
1669 assert(svc
!= NULL
|| inst
!= NULL
);
1670 assert(svc
== NULL
|| inst
== NULL
);
1673 h
= scf_instance_handle(inst
);
1675 h
= scf_service_handle(svc
);
1677 return (SCF_WALK_ERROR
);
1679 if (p
->pw_snapname
!= NULL
) {
1680 if (_get_snapshot(inst
, p
->pw_snapname
, &tmpl_snap
) == -1)
1681 return (SCF_WALK_ERROR
);
1683 pg
= _find_template_pg_match(svc
, inst
, tmpl_snap
, p
->pw_pgname
,
1684 p
->pw_pgtype
, p
->pw_target
, &tmpl_pg_name
);
1687 p
->pw_snap
= tmpl_snap
;
1689 p
->pw_tmpl_pgname
= tmpl_pg_name
;
1692 return (SCF_WALK_DONE
);
1695 scf_snapshot_destroy(tmpl_snap
);
1696 return (SCF_WALK_NEXT
);
1700 * return 0 on success and -1 on failure.
1701 * SCF_ERROR_CONNECTION_BROKEN
1703 * SCF_ERROR_HANDLE_DESTROYED
1704 * SCF_ERROR_HANDLE_MISMATCH
1705 * SCF_ERROR_INTERNAL
1706 * SCF_ERROR_INVALID_ARGUMENT
1707 * FMRI argument, snapshot name, pg_name, or pg is invalid.
1708 * SCF_ERROR_NO_MEMORY
1709 * SCF_ERROR_NO_RESOURCES
1710 * SCF_ERROR_NOT_BOUND
1711 * SCF_ERROR_NOT_FOUND
1715 scf_tmpl_get_by_pg(scf_propertygroup_t
*pg
, scf_pg_tmpl_t
*pg_tmpl
, int flags
)
1717 char *fmribuf
= NULL
, *snapbuf
= NULL
, *pg_name
= NULL
, *pg_type
= NULL
;
1719 ssize_t fbufsz
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
) + 1;
1720 ssize_t nbufsz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
1721 ssize_t tbufsz
= scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH
) + 1;
1722 scf_instance_t
*inst
= NULL
;
1723 scf_snaplevel_t
*snaplvl
= NULL
;
1724 scf_service_t
*svc
= NULL
;
1726 scf_snapshot_t
*snap
= NULL
;
1727 pg_tmpl_walk_t
*p
= NULL
;
1729 assert(fbufsz
!= 0 && nbufsz
!= 0 && tbufsz
!= 0);
1731 scf_tmpl_pg_reset(pg_tmpl
);
1733 if ((h
= scf_pg_handle(pg
)) == NULL
)
1736 if ((inst
= scf_instance_create(h
)) == NULL
||
1737 (svc
= scf_service_create(h
)) == NULL
||
1738 (snaplvl
= scf_snaplevel_create(h
)) == NULL
) {
1742 if ((fmribuf
= malloc(fbufsz
)) == NULL
||
1743 (pg_name
= malloc(nbufsz
)) == NULL
||
1744 (pg_type
= malloc(tbufsz
)) == NULL
||
1745 (p
= calloc(1, sizeof (pg_tmpl_walk_t
))) == NULL
) {
1746 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1750 if (scf_pg_get_name(pg
, pg_name
, nbufsz
) < 0) {
1754 if (scf_pg_get_type(pg
, pg_type
, tbufsz
) < 0) {
1757 p
->pw_pgname
= pg_name
;
1758 p
->pw_pgtype
= pg_type
;
1760 ret
= scf_pg_get_parent_snaplevel(pg
, snaplvl
);
1762 switch (scf_error()) {
1763 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1764 /* Parent type doesn't match. Keep looking. */
1767 case SCF_ERROR_DELETED
:
1768 case SCF_ERROR_NOT_BOUND
:
1769 case SCF_ERROR_NOT_SET
:
1770 /* Pass these back to the caller. */
1773 case SCF_ERROR_HANDLE_MISMATCH
:
1780 * No snapshot. We'll use 'editing' by default since
1781 * snap and snapbuf are NULL.
1783 p
->pw_snapname
= NULL
;
1786 if ((snap
= scf_snapshot_create(h
)) == NULL
) {
1790 ret
= scf_snaplevel_get_parent(snaplvl
, snap
);
1792 if (ismember(scf_error(), errors_server
)) {
1800 /* Grab snapshot name while we're here. */
1801 if ((snapbuf
= malloc(nbufsz
)) == NULL
) {
1802 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1805 if (scf_snapshot_get_name(snap
, snapbuf
, nbufsz
) < 0) {
1806 if (ismember(scf_error(), errors_server
)) {
1813 p
->pw_snapname
= snapbuf
;
1815 ret
= scf_snapshot_get_parent(snap
, inst
);
1817 if (ismember(scf_error(), errors_server
)) {
1825 _walk_template_instances(NULL
, inst
, snap
,
1826 (walk_template_inst_func_t
*)find_pg_match
, p
, flags
);
1829 /* No snapshot parent. Go looking for instance parent. */
1830 if (snapbuf
== NULL
) {
1831 /* First look for instance parent. */
1832 ret
= scf_pg_get_parent_instance(pg
, inst
);
1834 _walk_template_instances(NULL
, inst
, snap
,
1835 (walk_template_inst_func_t
*)find_pg_match
,
1837 /* OK, check for service parent */
1838 } else if (ret
== -1 &&
1839 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
1840 ret
= scf_pg_get_parent_service(pg
, svc
);
1842 _walk_template_instances(svc
, NULL
, snap
,
1843 (walk_template_inst_func_t
*)find_pg_match
,
1846 switch (scf_error()) {
1847 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1848 (void) scf_set_error(
1849 SCF_ERROR_NOT_FOUND
);
1852 case SCF_ERROR_CONNECTION_BROKEN
:
1853 case SCF_ERROR_DELETED
:
1854 case SCF_ERROR_HANDLE_MISMATCH
:
1855 case SCF_ERROR_NOT_BOUND
:
1856 case SCF_ERROR_NOT_SET
:
1869 if (p
->pw_pg
!= NULL
) {
1871 pg_tmpl
->pt_pg
= p
->pw_pg
;
1872 pg_tmpl
->pt_inst
= p
->pw_inst
;
1873 /* we may get a different instance back */
1874 if (p
->pw_inst
!= inst
)
1875 scf_instance_destroy(inst
);
1876 pg_tmpl
->pt_snap
= p
->pw_snap
;
1877 pg_tmpl
->pt_svc
= p
->pw_svc
;
1878 /* we may get a different service back */
1879 if (p
->pw_svc
!= svc
)
1880 scf_service_destroy(svc
);
1881 pg_tmpl
->pt_populated
= 1;
1882 free(p
->pw_tmpl_pgname
);
1887 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
1891 scf_instance_destroy(inst
);
1892 scf_service_destroy(svc
);
1894 scf_snapshot_destroy(snap
);
1900 scf_snaplevel_destroy(snaplvl
);
1905 * int scf_tmpl_get_by_pg_name()
1907 * Get a template by a combination of the name and type. Either name
1908 * or type can be null, which indicates a wildcard. flags may be
1909 * SCF_PG_TMPL_FLAG_CURRENT (use current properties rather than
1910 * the defined or running snapshot), and SCF_PG_TMPL_FLAG_EXACT (match
1911 * only templates defined by the FMRI in question, not by its restarter
1912 * or globally). Returns 0 on success and -1 on error, and sets
1914 * SCF_ERROR_BACKEND_ACCESS
1915 * SCF_ERROR_CONNECTION_BROKEN
1916 * The connection to the repository was lost.
1918 * The instance has been deleted.
1919 * SCF_ERROR_HANDLE_DESTROYED
1920 * SCF_ERROR_INTERNAL
1921 * SCF_ERROR_INVALID_ARGUMENT
1922 * FMRI isn't valid, pg_name is too long to look for a template, or
1923 * snapshot specified isn't a valid name
1924 * SCF_ERROR_NO_MEMORY
1925 * SCF_ERROR_NO_RESOURCES
1926 * The server does not have adequate resources to complete the request.
1927 * SCF_ERROR_NOT_BOUND
1928 * The handle is not currently bound.
1929 * SCF_ERROR_NOT_FOUND
1930 * Object matching FMRI doesn't exist in the repository, or snapshot
1934 scf_tmpl_get_by_pg_name(const char *fmri
, const char *snapshot
,
1935 const char *pg_name
, const char *pg_type
, scf_pg_tmpl_t
*pg_tmpl
, int flags
)
1937 scf_instance_t
*inst
= NULL
;
1938 scf_service_t
*svc
= NULL
;
1939 scf_snapshot_t
*snap
= NULL
;
1940 pg_tmpl_walk_t
*p
= NULL
;
1944 assert(pg_tmpl
!= NULL
);
1948 scf_tmpl_pg_reset(pg_tmpl
);
1950 if ((inst
= scf_instance_create(h
)) == NULL
||
1951 (svc
= scf_service_create(h
)) == NULL
) {
1955 p
= calloc(1, sizeof (pg_tmpl_walk_t
));
1957 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1961 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, inst
, NULL
,
1962 NULL
, SCF_DECODE_FMRI_EXACT
);
1964 scf_service_destroy(svc
);
1966 } else if (ret
!= 0 &&
1967 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
1968 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, svc
,
1969 NULL
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
);
1971 scf_instance_destroy(inst
);
1976 if (ismember(scf_error(), errors_server
)) {
1978 } else switch (scf_error()) {
1979 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1980 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1983 case SCF_ERROR_INVALID_ARGUMENT
:
1984 case SCF_ERROR_NOT_FOUND
:
1987 case SCF_ERROR_HANDLE_MISMATCH
:
1988 case SCF_ERROR_NOT_SET
:
1995 assert(svc
== NULL
|| inst
== NULL
);
1996 assert(svc
!= NULL
|| inst
!= NULL
);
1998 /* If we have a service fmri, snapshot is ignored. */
2000 if (snapshot
== NULL
|| strcmp(snapshot
, "running") == 0 ||
2001 (flags
& SCF_PG_TMPL_FLAG_CURRENT
) ==
2002 SCF_PG_TMPL_FLAG_CURRENT
) {
2003 if (_get_snapshot(inst
, NULL
, &snap
) == -1)
2006 if (_get_snapshot(inst
, snapshot
, &snap
) == -1) {
2008 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2014 p
->pw_snapname
= snapshot
;
2015 p
->pw_pgname
= pg_name
;
2016 p
->pw_pgtype
= pg_type
;
2019 * For each of instance, restarter, global
2020 * - check for a tm_pg_pattern_nt_<name> matching type
2021 * - check for a tm_pg_pattern_t_<type> matching type
2022 * - check for any tm_pg_pattern_
2023 * Currently plan to return the most specific match only.
2025 _walk_template_instances(svc
, inst
, snap
,
2026 (walk_template_inst_func_t
*)find_pg_match
, p
, flags
);
2028 if (p
->pw_pg
!= NULL
) {
2030 pg_tmpl
->pt_pg
= p
->pw_pg
;
2031 pg_tmpl
->pt_inst
= p
->pw_inst
;
2032 /* we may get a different instance back */
2033 if (p
->pw_inst
!= inst
)
2034 scf_instance_destroy(inst
);
2035 pg_tmpl
->pt_snap
= p
->pw_snap
;
2036 pg_tmpl
->pt_svc
= p
->pw_svc
;
2037 /* we may get a different service back */
2038 if (p
->pw_svc
!= svc
)
2039 scf_service_destroy(svc
);
2040 pg_tmpl
->pt_populated
= 1;
2041 scf_snapshot_destroy(snap
);
2042 free(p
->pw_tmpl_pgname
);
2047 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
2050 scf_instance_destroy(inst
);
2051 scf_service_destroy(svc
);
2052 scf_snapshot_destroy(snap
);
2057 * Returns NULL on failure, sets scf_error() to _CONNECTION_BROKEN,
2058 * _DELETED, _NO_RESOURCES, or _NOT_BOUND.
2061 _get_svc_or_inst_iter(scf_handle_t
*h
, scf_pg_tmpl_t
*t
)
2066 assert(t
->pt_svc
!= NULL
|| t
->pt_inst
!= NULL
);
2067 assert(t
->pt_svc
== NULL
|| t
->pt_inst
== NULL
);
2069 if ((iter
= scf_iter_create(h
)) == NULL
) {
2073 /* Iterate on property groups of type template_pg_pattern */
2075 if (t
->pt_inst
!= NULL
)
2076 ret
= scf_iter_instance_pgs_typed_composed(iter
,
2077 t
->pt_inst
, t
->pt_snap
,
2078 SCF_GROUP_TEMPLATE_PG_PATTERN
);
2079 if (t
->pt_svc
!= NULL
)
2080 ret
= scf_iter_service_pgs_typed(iter
, t
->pt_svc
,
2081 SCF_GROUP_TEMPLATE_PG_PATTERN
);
2084 if (ismember(scf_error(), errors_server
)) {
2085 scf_iter_destroy(iter
);
2097 * Returns NULL on failure, sets scf_error() to:
2098 * SCF_ERROR_BACKEND_ACCESS
2099 * SCF_ERROR_CONNECTION_BROKEN
2101 * SCF_HANDLE_DESTROYED
2102 * SCF_ERROR_INTERNAL
2103 * SCF_ERROR_INVALID_ARGUMENT
2104 * Handle argument is NULL, or snaphot is not a valid snapshot name.
2105 * SCF_ERROR_NO_MEMORY
2106 * SCF_ERROR_NO_RESOURCES
2107 * SCF_ERROR_NOT_BOUND
2108 * SCF_ERROR_NOT_FOUND
2111 _get_next_iterator(scf_handle_t
*h
, scf_pg_tmpl_t
*t
, const char *snapshot
,
2114 scf_iter_t
*iter
= NULL
;
2117 limit
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
2121 * Check what level we last iterated on: none, service,
2122 * restarter, or global. Make sure that if one in the middle
2123 * doesn't exist, we move on to the next entity.
2125 * Before we drop any references to pt_inst or pt_svc we must
2126 * destroy them so we don't leak them.
2129 switch (t
->pt_iter_last
) {
2130 case SCF__TMPL_ITER_NONE
:
2131 t
->pt_iter_last
= SCF__TMPL_ITER_INST
;
2132 if (t
->pt_inst
!= t
->pt_orig_inst
)
2133 scf_instance_destroy(t
->pt_inst
);
2134 t
->pt_inst
= t
->pt_orig_inst
;
2135 if (t
->pt_svc
!= t
->pt_orig_svc
)
2136 scf_service_destroy(t
->pt_svc
);
2137 t
->pt_svc
= t
->pt_orig_svc
;
2140 case SCF__TMPL_ITER_INST
:
2142 * Don't go any further than the specified instance
2146 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
2149 t
->pt_iter_last
= SCF__TMPL_ITER_RESTARTER
;
2150 if (t
->pt_inst
!= t
->pt_orig_inst
)
2151 scf_instance_destroy(t
->pt_inst
);
2152 t
->pt_inst
= _get_restarter_inst(h
, t
->pt_orig_svc
,
2153 t
->pt_orig_inst
, t
->pt_snap
);
2154 if (t
->pt_svc
!= t
->pt_orig_svc
)
2155 scf_service_destroy(t
->pt_svc
);
2159 case SCF__TMPL_ITER_RESTARTER
:
2160 t
->pt_iter_last
= SCF__TMPL_ITER_GLOBAL
;
2161 if (t
->pt_inst
!= t
->pt_orig_inst
)
2162 scf_instance_destroy(t
->pt_inst
);
2163 t
->pt_inst
= _get_global_inst(h
);
2164 if (t
->pt_svc
!= t
->pt_orig_svc
)
2165 scf_service_destroy(t
->pt_svc
);
2169 case SCF__TMPL_ITER_GLOBAL
:
2170 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
2177 } while (t
->pt_inst
== NULL
&& t
->pt_svc
== NULL
);
2179 /* Set pt_snap to the snapshot for this instance */
2180 if (t
->pt_inst
!= NULL
) {
2181 scf_snapshot_destroy(t
->pt_snap
);
2182 if (_get_snapshot(t
->pt_inst
, snapshot
,
2187 iter
= _get_svc_or_inst_iter(h
, t
);
2193 * scf_pg_tmpl_t *scf_tmpl_pg_create(scf_handle_t *)
2195 * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT
2199 scf_tmpl_pg_create(scf_handle_t
*handle
)
2201 scf_pg_tmpl_t
*pg_tmpl
= NULL
;
2203 if (handle
== NULL
) {
2204 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2207 pg_tmpl
= calloc(1, sizeof (scf_pg_tmpl_t
));
2208 if (pg_tmpl
== NULL
)
2209 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2211 pg_tmpl
->pt_h
= handle
;
2217 * Retrieves name or type of a template pg.
2218 * Returns -1 on failure. Sets scf_error():
2219 * SCF_ERROR_BACKEND_ACCESS
2220 * SCF_ERROR_CONNECTION_BROKEN
2222 * SCF_ERROR_HANDLE_DESTROYED
2223 * SCF_ERROR_INTERNAL
2224 * SCF_ERROR_NO_MEMORY
2225 * SCF_ERROR_NO_RESOURCES
2226 * SCF_ERROR_NOT_BOUND
2227 * SCF_ERROR_PERMISSION_DENIED
2228 * SCF_ERROR_TEMPLATE_INVALID
2229 * pname property is not SCF_TYPE_ASTRING or has more than one value.
2232 _scf_tmpl_prop_value(scf_propertygroup_t
*pg
, const char *pname
, char **out
)
2234 assert(strcmp(pname
, SCF_PROPERTY_TM_NAME
) == 0 ||
2235 strcmp(pname
, SCF_PROPERTY_TM_TYPE
) == 0);
2237 *out
= _scf_read_single_astring_from_pg(pg
, pname
);
2239 if (*out
!= NULL
&& *out
[0] == '\0') {
2240 (void) scf_set_error(SCF_ERROR_NONE
);
2242 *out
= strdup(SCF_TMPL_WILDCARD
);
2244 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2247 if (ismember(scf_error(), errors_server
)) {
2249 } else switch (scf_error()) {
2250 case SCF_ERROR_CONSTRAINT_VIOLATED
:
2251 case SCF_ERROR_NOT_FOUND
:
2252 case SCF_ERROR_TYPE_MISMATCH
:
2253 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
2256 case SCF_ERROR_INVALID_ARGUMENT
:
2257 case SCF_ERROR_NOT_SET
:
2264 return (strlen(*out
));
2268 * int scf_tmpl_iter_pgs()
2270 * Iterates through the property group templates for the fmri given.
2271 * When t is uninitialized or reset, sets t to the first property group
2272 * template in fmri. On subsequent calls, sets t to the next property group
2274 * Returns 1 on success, 0 when no property group templates are left to
2275 * iterate, -1 on error.
2276 * The flags argument may include SCF_PG_TMPL_FLAG_REQUIRED,
2277 * SCF_PG_TMPL_FLAG_CURRENT, and/or SCF_PG_TMPL_FLAG_EXACT.
2279 * Returns -1 on error and sets scf_error() to:
2280 * SCF_ERROR_BACKEND_ACCESS
2281 * SCF_ERROR_CONNECTION_BROKEN
2283 * SCF_ERROR_HANDLE_DESTROYED
2284 * SCF_ERROR_INTERNAL
2285 * SCF_ERROR_INVALID_ARGUMENT
2286 * The handle argument is NULL, fmri is invalid, or snapshot is invalid.
2287 * SCF_ERROR_NO_MEMORY
2288 * SCF_ERROR_NO_RESOURCES
2289 * SCF_ERROR_NOT_BOUND
2290 * SCF_ERROR_NOT_FOUND
2291 * SCF_ERROR_PERMISSION_DENIED
2294 scf_tmpl_iter_pgs(scf_pg_tmpl_t
*t
, const char *fmri
, const char *snapshot
,
2295 const char *type
, int flags
)
2298 scf_service_t
*svc
= NULL
;
2299 scf_instance_t
*inst
= NULL
;
2300 scf_propertygroup_t
*pg
= NULL
;
2301 scf_snapshot_t
*snap
= NULL
;
2302 scf_pg_tmpl_t
*pg_tmpl
= NULL
;
2310 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2316 if (t
->pt_populated
== 0) {
2317 if ((svc
= scf_service_create(h
)) == NULL
||
2318 (inst
= scf_instance_create(h
)) == NULL
||
2319 (pg
= scf_pg_create(h
)) == NULL
) {
2320 goto fail_non_populated
;
2323 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, inst
, NULL
,
2324 NULL
, SCF_DECODE_FMRI_EXACT
);
2326 scf_service_destroy(svc
);
2328 } else if (ret
!= 0 &&
2329 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
2330 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, svc
,
2331 NULL
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
);
2333 scf_instance_destroy(inst
);
2339 if (ismember(scf_error(), errors_server
)) {
2340 goto fail_non_populated
;
2341 } else switch (scf_error()) {
2342 case SCF_ERROR_CONSTRAINT_VIOLATED
:
2343 (void) scf_set_error(
2344 SCF_ERROR_INVALID_ARGUMENT
);
2345 goto fail_non_populated
;
2347 case SCF_ERROR_INVALID_ARGUMENT
:
2348 case SCF_ERROR_NOT_FOUND
:
2349 goto fail_non_populated
;
2351 case SCF_ERROR_HANDLE_MISMATCH
:
2352 case SCF_ERROR_NOT_SET
:
2359 assert(svc
== NULL
|| inst
== NULL
);
2360 assert(svc
!= NULL
|| inst
!= NULL
);
2363 if (snapshot
== NULL
||
2364 strcmp(snapshot
, "running") == 0 ||
2365 (flags
& SCF_PG_TMPL_FLAG_CURRENT
) ==
2366 SCF_PG_TMPL_FLAG_CURRENT
) {
2367 if (_get_snapshot(inst
, NULL
, &snap
) == -1)
2368 goto fail_non_populated
;
2370 (void) scf_set_error(SCF_ERROR_NONE
);
2371 if (_get_snapshot(inst
, snapshot
,
2373 goto fail_non_populated
;
2374 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2375 goto fail_non_populated
;
2379 scf_snapshot_destroy(snap
);
2384 pg_tmpl
->pt_orig_inst
= inst
;
2385 pg_tmpl
->pt_orig_svc
= svc
;
2386 pg_tmpl
->pt_snap
= snap
;
2387 pg_tmpl
->pt_is_iter
= 1;
2388 pg_tmpl
->pt_iter_last
= SCF__TMPL_ITER_NONE
;
2389 pg_tmpl
->pt_pg
= pg
;
2390 pg_tmpl
->pt_populated
= 1;
2392 if (t
->pt_is_iter
!= 1) {
2393 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2397 assert(pg_tmpl
->pt_pg
!= NULL
);
2400 if (pg_tmpl
->pt_iter
== NULL
) {
2401 pg_tmpl
->pt_iter
= _get_next_iterator(h
, pg_tmpl
, snapshot
,
2402 (flags
& SCF_PG_TMPL_FLAG_EXACT
) ? 1 : 0);
2403 if (pg_tmpl
->pt_iter
== NULL
) {
2404 if (scf_error() == SCF_ERROR_NOT_FOUND
)
2411 while (found
== 0) {
2412 while ((err
= scf_iter_next_pg(pg_tmpl
->pt_iter
,
2413 pg_tmpl
->pt_pg
)) != 1) {
2415 if (ismember(scf_error(), errors_server
)) {
2417 } else switch (scf_error()) {
2418 case SCF_ERROR_HANDLE_MISMATCH
:
2421 case SCF_ERROR_NOT_SET
:
2422 case SCF_ERROR_INVALID_ARGUMENT
:
2427 } else if (err
== 0) {
2428 /* This iteration is done. Get the next one */
2429 scf_iter_destroy(pg_tmpl
->pt_iter
);
2430 pg_tmpl
->pt_iter
= _get_next_iterator(h
,
2432 (flags
& SCF_PG_TMPL_FLAG_EXACT
) ? 1 : 0);
2433 if (pg_tmpl
->pt_iter
== NULL
) {
2434 if (scf_error() == SCF_ERROR_NOT_FOUND
)
2447 * Discard pgs which don't exist at the right scoping. This
2448 * check also makes sure that if we're looking at, for
2449 * example, svc:/system/svc/restarter:default, that we
2450 * don't hand back the same property groups twice.
2452 switch (t
->pt_iter_last
) {
2453 case SCF__TMPL_ITER_INST
:
2454 ret
= check_target_match(pg_tmpl
->pt_pg
,
2455 SCF_TM_TARGET_THIS
);
2457 case SCF__TMPL_ITER_RESTARTER
:
2458 ret
= check_target_match(pg_tmpl
->pt_pg
,
2459 SCF_TM_TARGET_DELEGATE
);
2461 case SCF__TMPL_ITER_GLOBAL
:
2462 ret
= check_target_match(pg_tmpl
->pt_pg
,
2465 case SCF__TMPL_ITER_NONE
:
2475 * If walking only required property groups, check if
2476 * the retrieved group is required.
2478 if (flags
& SCF_PG_TMPL_FLAG_REQUIRED
) {
2479 if (scf_tmpl_pg_required(pg_tmpl
, &required
) == 0) {
2488 * If type != NULL, check if type property matches. If no
2489 * type property exists, consider it a match.
2492 if (scf_tmpl_pg_type(pg_tmpl
, &tmpl_type
) != -1) {
2493 if (strcmp(tmpl_type
, SCF_TMPL_WILDCARD
)
2494 == 0 || strcmp(type
, tmpl_type
) == 0) {
2499 } else if (scf_error() == SCF_ERROR_NOT_FOUND
||
2500 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
||
2501 scf_error() == SCF_ERROR_TYPE_MISMATCH
) {
2514 scf_service_destroy(svc
);
2515 scf_instance_destroy(inst
);
2517 scf_snapshot_destroy(snap
);
2522 scf_tmpl_pg_destroy(scf_pg_tmpl_t
*t
)
2527 scf_pg_destroy(t
->pt_pg
);
2528 scf_instance_destroy(t
->pt_inst
);
2529 if (t
->pt_inst
!= t
->pt_orig_inst
)
2530 scf_instance_destroy(t
->pt_orig_inst
);
2531 scf_snapshot_destroy(t
->pt_snap
);
2532 scf_service_destroy(t
->pt_orig_svc
);
2533 if (t
->pt_svc
!= t
->pt_orig_svc
)
2534 scf_service_destroy(t
->pt_svc
);
2535 scf_iter_destroy(t
->pt_iter
);
2540 scf_tmpl_pg_reset(scf_pg_tmpl_t
*t
)
2542 scf_pg_destroy(t
->pt_pg
);
2545 scf_instance_destroy(t
->pt_inst
);
2546 if (t
->pt_inst
!= t
->pt_orig_inst
)
2547 scf_instance_destroy(t
->pt_orig_inst
);
2549 t
->pt_orig_inst
= NULL
;
2551 scf_snapshot_destroy(t
->pt_snap
);
2554 scf_service_destroy(t
->pt_orig_svc
);
2555 if (t
->pt_svc
!= t
->pt_orig_svc
)
2556 scf_service_destroy(t
->pt_svc
);
2557 t
->pt_orig_svc
= NULL
;
2560 scf_iter_destroy(t
->pt_iter
);
2563 t
->pt_populated
= 0;
2565 t
->pt_iter_last
= 0;
2567 /* Do not reset t->pt_h. */
2571 * int scf_tmpl_get_by_prop()
2573 * Get the property template given a property group template and property
2574 * name. No flags are currently defined for this function.
2576 * Returns NULL on failure, and sets scf_error():
2577 * SCF_ERROR_BACKEND_ACCESS
2578 * SCF_ERROR_CONNECTION_BROKEN
2580 * SCF_ERROR_HANDLE_DESTROYED
2581 * SCF_ERROR_INTERNAL
2582 * SCF_ERROR_INVALID_ARGUMENT
2583 * SCF_ERROR_NO_MEMORY
2584 * SCF_ERROR_NO_RESOURCES
2585 * SCF_ERROR_NOT_BOUND
2586 * SCF_ERROR_NOT_FOUND
2587 * Template object matching property doesn't exist in the repository.
2588 * SCF_ERROR_TYPE_MISMATCH
2589 * Matching template object is the wrong type in the repository.
2592 scf_tmpl_get_by_prop(scf_pg_tmpl_t
*t
, const char *prop
,
2593 scf_prop_tmpl_t
*prop_tmpl
, int flags
)
2595 char *tmpl_prop_name
;
2596 scf_propertygroup_t
*pg
= NULL
;
2601 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2605 scf_tmpl_prop_reset(prop_tmpl
);
2606 if ((pg
= scf_pg_create(scf_pg_handle(t
->pt_pg
))) == NULL
)
2609 tmpl_prop_name
= _tmpl_prop_name(prop
, t
);
2610 if (tmpl_prop_name
== NULL
) {
2611 assert(scf_error() != SCF_ERROR_NOT_SET
);
2615 if (_get_pg(t
->pt_svc
, t
->pt_inst
, t
->pt_snap
,
2616 tmpl_prop_name
, pg
) != 0) {
2617 if (!ismember(scf_error(), errors_server
)) {
2618 switch (scf_error()) {
2619 case SCF_ERROR_NOT_FOUND
:
2620 case SCF_ERROR_INVALID_ARGUMENT
:
2623 case SCF_ERROR_NOT_SET
:
2624 case SCF_ERROR_HANDLE_MISMATCH
:
2632 * We've only found a template property group if the type
2635 if ((pg_type
= _scf_get_pg_type(pg
)) != NULL
&&
2636 strcmp(pg_type
, SCF_GROUP_TEMPLATE_PROP_PATTERN
) == 0)
2639 (void) scf_set_error(SCF_ERROR_TYPE_MISMATCH
);
2647 free(tmpl_prop_name
);
2651 prop_tmpl
->prt_h
= scf_pg_handle(t
->pt_pg
);
2652 prop_tmpl
->prt_t
= t
;
2653 prop_tmpl
->prt_pg
= pg
;
2654 prop_tmpl
->prt_pg_name
= tmpl_prop_name
;
2655 prop_tmpl
->prt_populated
= 1;
2661 * scf_prop_tmpl_t *scf_tmpl_prop_create(scf_handle_t *);
2663 * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT, or
2667 scf_tmpl_prop_create(scf_handle_t
*handle
)
2669 scf_prop_tmpl_t
*pt
;
2671 if (handle
== NULL
) {
2672 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2675 pt
= calloc(1, sizeof (scf_prop_tmpl_t
));
2677 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2685 * int scf_tmpl_iter_props()
2687 * Iterates over all property templates defined in the specified property
2688 * group template. The iterator state is stored on the property template
2689 * data structure, and the data structure should be allocated with
2690 * scf_tmpl_prop_create(). To continue the iteration, the previously
2691 * returned structure should be passed in as an argument to this function.
2692 * flags can include SCF_PROP_TMPL_FLAG_REQUIRED. The function returns
2693 * 1 when a result was found, and 0 when the iteration is complete.
2695 * Returns -1 on failure, and sets scf_error():
2696 * SCF_ERROR_BACKEND_ACCESS
2697 * SCF_ERROR_CONNECTION_BROKEN
2699 * SCF_ERROR_HANDLE_DESTROYED
2700 * SCF_ERROR_INTERNAL
2701 * SCF_ERROR_INVALID_ARGUMENT
2702 * SCF_ERROR_NO_MEMORY
2703 * SCF_ERROR_NO_RESOURCES
2704 * SCF_ERROR_NOT_BOUND
2705 * SCF_ERROR_PERMISSION_DENIED
2706 * SCF_ERROR_TEMPLATE_INVALID
2707 * Template data is invalid. One of the property templates in this
2708 * pg_tmpl is malformed.
2711 scf_tmpl_iter_props(scf_pg_tmpl_t
*t
, scf_prop_tmpl_t
*pt
, int flags
)
2713 scf_prop_tmpl_t
*prop_tmpl
;
2715 char *pg_name
= NULL
;
2718 ssize_t size
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
2721 scf_propertygroup_t
*pg
= NULL
;
2722 scf_iter_t
*iter
= NULL
;
2725 if (t
== NULL
|| pt
== NULL
) {
2726 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2730 assert(t
->pt_inst
== NULL
|| t
->pt_svc
== NULL
);
2731 assert(t
->pt_inst
!= NULL
|| t
->pt_svc
!= NULL
);
2733 if ((pg_name
= malloc(size
)) == NULL
) {
2734 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2738 if (pt
->prt_populated
== 0) {
2739 if ((h
= scf_pg_handle(t
->pt_pg
)) == NULL
)
2740 goto fail_non_populated
;
2742 if ((pg
= scf_pg_create(h
)) == NULL
||
2743 (iter
= scf_iter_create(h
)) == NULL
)
2744 goto fail_non_populated
;
2746 if (t
->pt_inst
!= NULL
)
2747 err
= scf_iter_instance_pgs_typed_composed(iter
,
2748 t
->pt_inst
, t
->pt_snap
,
2749 SCF_GROUP_TEMPLATE_PROP_PATTERN
);
2750 else if (t
->pt_svc
!= NULL
)
2751 err
= scf_iter_service_pgs_typed(iter
, t
->pt_svc
,
2752 SCF_GROUP_TEMPLATE_PROP_PATTERN
);
2755 if (ismember(scf_error(), errors_server
)) {
2756 goto fail_non_populated
;
2757 } else switch (scf_error()) {
2758 case SCF_ERROR_INVALID_ARGUMENT
:
2759 goto fail_non_populated
;
2761 case SCF_ERROR_NOT_SET
:
2762 case SCF_ERROR_HANDLE_MISMATCH
:
2770 prop_tmpl
->prt_t
= t
;
2771 prop_tmpl
->prt_populated
= 1;
2772 prop_tmpl
->prt_pg
= pg
;
2773 prop_tmpl
->prt_iter
= iter
;
2778 while ((err
= scf_iter_next_pg(prop_tmpl
->prt_iter
,
2779 prop_tmpl
->prt_pg
)) > 0) {
2781 * Check if the name matches the appropriate property
2782 * group template name.
2784 pg_pat
= _scf_read_single_astring_from_pg(prop_tmpl
->prt_pg
,
2785 SCF_PROPERTY_TM_PG_PATTERN
);
2786 if (pg_pat
== NULL
) {
2787 if (ismember(scf_error(), errors_server
)) {
2790 } else switch (scf_error()) {
2791 case SCF_ERROR_NOT_FOUND
:
2794 case SCF_ERROR_CONSTRAINT_VIOLATED
:
2795 case SCF_ERROR_TYPE_MISMATCH
:
2796 (void) scf_set_error(
2797 SCF_ERROR_TEMPLATE_INVALID
);
2801 case SCF_ERROR_INVALID_ARGUMENT
:
2802 case SCF_ERROR_NOT_SET
:
2808 if ((ret
= scf_pg_get_name(t
->pt_pg
, pg_name
, size
)) <= 0) {
2813 if (ismember(scf_error(), errors_server
)) {
2821 if (strcmp(pg_pat
, pg_name
) != 0) {
2828 * If walking only required properties, check if
2829 * the retrieved property is required.
2831 if (flags
& SCF_PROP_TMPL_FLAG_REQUIRED
) {
2832 if (scf_tmpl_prop_required(prop_tmpl
, &required
) == 0) {
2845 if (ismember(scf_error(), errors_server
)) {
2852 } else if (err
== 0) {
2853 scf_iter_destroy(prop_tmpl
->prt_iter
);
2854 prop_tmpl
->prt_iter
= NULL
;
2855 prop_tmpl
->prt_populated
= 0;
2864 scf_iter_destroy(iter
);
2869 scf_tmpl_prop_destroy(scf_prop_tmpl_t
*t
)
2874 scf_pg_destroy(t
->prt_pg
);
2875 free(t
->prt_pg_name
);
2881 scf_tmpl_prop_reset(scf_prop_tmpl_t
*t
)
2883 scf_pg_destroy(t
->prt_pg
);
2886 free(t
->prt_pg_name
);
2887 t
->prt_pg_name
= NULL
;
2892 t
->prt_populated
= 0;
2898 * Returns -1 on failure. Sets scf_error():
2899 * SCF_ERROR_BACKEND_ACCESS
2900 * SCF_ERROR_CONNECTION_BROKEN
2902 * SCF_ERROR_HANDLE_DESTROYED
2903 * SCF_ERROR_INTERNAL
2904 * SCF_ERROR_NO_MEMORY
2905 * SCF_ERROR_NO_RESOURCES
2906 * SCF_ERROR_NOT_BOUND
2907 * SCF_ERROR_PERMISSION_DENIED
2908 * SCF_ERROR_TEMPLATE_INVALID
2909 * The name of the template property group (the pname property) has
2910 * an improper repository format and is not type astring or has
2911 * more than one value.
2914 scf_tmpl_pg_name(const scf_pg_tmpl_t
*t
, char **out
)
2916 return (_scf_tmpl_prop_value(t
->pt_pg
, SCF_PROPERTY_TM_NAME
, out
));
2920 * returns an allocated string that must be freed
2922 * Returns NULL on failure, sets scf_error() to:
2923 * SCF_ERROR_BACKEND_ACCESS
2924 * SCF_ERROR_CONNECTION_BROKEN
2926 * SCF_ERROR_HANDLE_DESTROYED
2927 * SCF_ERROR_INTERNAL
2928 * SCF_ERROR_INVALID_ARGUMENT
2929 * name not a valid property name
2930 * name and locale are too long to make a property name
2931 * SCF_ERROR_NO_MEMORY
2932 * SCF_ERROR_NO_RESOURCES
2933 * SCF_ERROR_NOT_BOUND
2934 * SCF_ERROR_NOT_FOUND
2935 * Property doesn't exist or exists and has no value.
2936 * SCF_ERROR_PERMISSION_DENIED
2937 * SCF_ERROR_TEMPLATE_INVALID
2940 _read_localized_astring_from_pg(scf_propertygroup_t
*pg
, const char *name
,
2946 str
= _add_locale_to_name(name
, locale
);
2949 lname_prop
= _scf_read_single_astring_from_pg(pg
, str
);
2950 if (lname_prop
== NULL
) {
2952 if (scf_error() != SCF_ERROR_NOT_FOUND
)
2954 str
= _add_locale_to_name(name
, "C");
2957 lname_prop
= _scf_read_single_astring_from_pg(pg
, str
);
2960 if (lname_prop
== NULL
) {
2961 if (scf_error() == SCF_ERROR_TYPE_MISMATCH
||
2962 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
)
2963 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
2965 return (lname_prop
);
2969 * returns an allocated string that must be freed
2971 * Returns -1 on failure, sets scf_error() to:
2972 * SCF_ERROR_BACKEND_ACCESS
2973 * SCF_ERROR_CONNECTION_BROKEN
2975 * SCF_ERROR_HANDLE_DESTROYED
2976 * SCF_ERROR_INTERNAL
2977 * SCF_ERROR_INVALID_ARGUMENT
2978 * locale is too long to make a valid property name
2979 * SCF_ERROR_NO_MEMORY
2980 * SCF_ERROR_NO_RESOURCES
2981 * SCF_ERROR_NOT_BOUND
2982 * SCF_ERROR_NOT_FOUND
2983 * Property doesn't exist or exists and has no value.
2984 * SCF_ERROR_PERMISSION_DENIED
2985 * SCF_ERROR_TEMPLATE_INVALID
2988 scf_tmpl_pg_common_name(const scf_pg_tmpl_t
*t
, const char *locale
, char **out
)
2990 assert(out
!= NULL
);
2991 if ((*out
= _read_localized_astring_from_pg(t
->pt_pg
,
2992 SCF_PROPERTY_TM_COMMON_NAME_PREFIX
, locale
)) == NULL
)
2995 return (strlen(*out
));
2999 * returns an allocated string that must be freed
3001 * Returns -1 on failure, sets scf_error() to:
3002 * SCF_ERROR_BACKEND_ACCESS
3003 * SCF_ERROR_CONNECTION_BROKEN
3005 * SCF_ERROR_HANDLE_DESTROYED
3006 * SCF_ERROR_INTERNAL
3007 * SCF_ERROR_INVALID_ARGUMENT
3008 * locale is too long to make a valid property name
3009 * SCF_ERROR_NO_MEMORY
3010 * SCF_ERROR_NO_RESOURCES
3011 * SCF_ERROR_NOT_BOUND
3012 * SCF_ERROR_NOT_FOUND
3013 * Property doesn't exist or exists and has no value.
3014 * SCF_ERROR_PERMISSION_DENIED
3015 * SCF_ERROR_TEMPLATE_INVALID
3018 scf_tmpl_pg_description(const scf_pg_tmpl_t
*t
, const char *locale
, char **out
)
3020 assert(out
!= NULL
);
3021 if ((*out
= _read_localized_astring_from_pg(t
->pt_pg
,
3022 SCF_PROPERTY_TM_DESCRIPTION_PREFIX
, locale
)) == NULL
)
3025 return (strlen(*out
));
3029 * Returns -1 on failure. Sets scf_error():
3030 * SCF_ERROR_BACKEND_ACCESS
3031 * SCF_ERROR_CONNECTION_BROKEN
3033 * SCF_ERROR_HANDLE_DESTROYED
3034 * SCF_ERROR_INTERNAL
3035 * SCF_ERROR_NO_MEMORY
3036 * SCF_ERROR_NO_RESOURCES
3037 * SCF_ERROR_NOT_BOUND
3038 * SCF_ERROR_NOT_FOUND
3039 * 'type' property doesn't exist or exists and has no value.
3040 * SCF_ERROR_PERMISSION_DENIED
3041 * SCF_ERROR_TEMPLATE_INVALID
3042 * 'type' property is not SCF_TYPE_ASTRING or has more than one value.
3045 scf_tmpl_pg_type(const scf_pg_tmpl_t
*t
, char **out
)
3047 return (_scf_tmpl_prop_value(t
->pt_pg
, SCF_PROPERTY_TM_TYPE
, out
));
3051 * Returns -1 on failure, sets scf_error() to:
3052 * SCF_ERROR_BACKEND_ACCESS
3053 * SCF_ERROR_CONNECTION_BROKEN
3055 * SCF_ERROR_HANDLE_DESTROYED
3056 * SCF_ERROR_INTERNAL
3057 * SCF_ERROR_NO_MEMORY
3058 * SCF_ERROR_NO_RESOURCES
3059 * SCF_ERROR_NOT_BOUND
3060 * SCF_ERROR_PERMISSION_DENIED
3061 * SCF_ERROR_TEMPLATE_INVALID
3062 * required property is not SCF_TYPE_BOOLEAN or has more than one value.
3065 scf_tmpl_pg_required(const scf_pg_tmpl_t
*t
, uint8_t *out
)
3068 if (_read_single_boolean_from_pg(t
->pt_pg
, SCF_PROPERTY_TM_REQUIRED
,
3070 if (ismember(scf_error(), errors_server
)) {
3072 } else switch (scf_error()) {
3073 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3074 case SCF_ERROR_TYPE_MISMATCH
:
3075 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3078 case SCF_ERROR_NOT_FOUND
:
3082 case SCF_ERROR_INVALID_ARGUMENT
:
3093 * Returns -1 on failure. Sets scf_error():
3094 * SCF_ERROR_BACKEND_ACCESS
3095 * SCF_ERROR_CONNECTION_BROKEN
3097 * SCF_ERROR_HANDLE_DESTROYED
3098 * SCF_ERROR_INTERNAL
3099 * SCF_ERROR_NO_MEMORY
3100 * SCF_ERROR_NO_RESOURCES
3101 * SCF_ERROR_NOT_BOUND
3102 * SCF_ERROR_PERMISSION_DENIED
3103 * SCF_ERROR_TEMPLATE_INVALID
3104 * target property is not SCF_TYPE_ASTRING or has more than one value.
3107 scf_tmpl_pg_target(const scf_pg_tmpl_t
*t
, char **out
)
3109 *out
= _scf_read_single_astring_from_pg(t
->pt_pg
,
3110 SCF_PROPERTY_TM_TARGET
);
3113 if (ismember(scf_error(), errors_server
)) {
3115 } else switch (scf_error()) {
3116 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3117 case SCF_ERROR_NOT_FOUND
:
3118 case SCF_ERROR_TYPE_MISMATCH
:
3119 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3122 case SCF_ERROR_INVALID_ARGUMENT
:
3123 case SCF_ERROR_NOT_SET
:
3130 return (strlen(*out
));
3134 * Returns -1 on failure. Sets scf_error():
3135 * SCF_ERROR_BACKEND_ACCESS
3136 * SCF_ERROR_CONNECTION_BROKEN
3138 * SCF_ERROR_HANDLE_DESTROYED
3139 * SCF_ERROR_INTERNAL
3140 * SCF_ERROR_NO_MEMORY
3141 * SCF_ERROR_NO_RESOURCES
3142 * SCF_ERROR_NOT_BOUND
3143 * SCF_ERROR_PERMISSION_DENIED
3144 * SCF_ERROR_TEMPLATE_INVALID
3147 scf_tmpl_prop_name(const scf_prop_tmpl_t
*t
, char **out
)
3149 *out
= _scf_read_single_astring_from_pg(t
->prt_pg
,
3150 SCF_PROPERTY_TM_NAME
);
3152 if (*out
!= NULL
&& *out
[0] == '\0') {
3155 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3158 if (ismember(scf_error(), errors_server
)) {
3160 } else switch (scf_error()) {
3161 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3162 case SCF_ERROR_NOT_FOUND
:
3163 case SCF_ERROR_TEMPLATE_INVALID
:
3164 case SCF_ERROR_TYPE_MISMATCH
:
3165 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3168 case SCF_ERROR_INVALID_ARGUMENT
:
3169 case SCF_ERROR_NOT_SET
:
3176 return (strlen(*out
));
3180 * Returns -1 on failure. Sets scf_error():
3181 * SCF_ERROR_BACKEND_ACCESS
3182 * SCF_ERROR_CONNECTION_BROKEN
3184 * SCF_ERROR_HANDLE_DESTROYED
3185 * SCF_ERROR_INTERNAL
3186 * SCF_ERROR_NO_MEMORY
3187 * SCF_ERROR_NO_RESOURCES
3188 * SCF_ERROR_NOT_BOUND
3189 * SCF_ERROR_NOT_FOUND
3190 * 'type' property doesn't exist or exists and has no value.
3191 * SCF_ERROR_PERMISSION_DENIED
3192 * SCF_ERROR_TEMPLATE_INVALID
3193 * 'type' property is not SCF_TYPE_ASTRING, has more than one value,
3194 * is SCF_TYPE_INVALID, or is the empty string.
3197 scf_tmpl_prop_type(const scf_prop_tmpl_t
*t
, scf_type_t
*out
)
3201 type
= _scf_read_single_astring_from_pg(t
->prt_pg
,
3202 SCF_PROPERTY_TM_TYPE
);
3203 if (type
!= NULL
&& type
[0] == '\0') {
3205 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3209 if (ismember(scf_error(), errors_server
)) {
3211 } else switch (scf_error()) {
3212 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3213 case SCF_ERROR_TYPE_MISMATCH
:
3214 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3217 case SCF_ERROR_NOT_FOUND
:
3220 case SCF_ERROR_INVALID_ARGUMENT
:
3221 case SCF_ERROR_NOT_SET
:
3228 *out
= scf_string_to_type(type
);
3231 if (*out
== SCF_TYPE_INVALID
) {
3232 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3240 * Returns -1 on failure, sets scf_error() to:
3241 * SCF_ERROR_BACKEND_ACCESS
3242 * SCF_ERROR_CONNECTION_BROKEN
3244 * Property group which represents t was deleted.
3245 * SCF_ERROR_HANDLE_DESTROYED
3246 * SCF_ERROR_INTERNAL
3247 * SCF_ERROR_NO_MEMORY
3248 * SCF_ERROR_NO_RESOURCES
3249 * SCF_ERROR_NOT_BOUND
3250 * SCF_ERROR_PERMISSION_DENIED
3251 * SCF_ERROR_TEMPLATE_INVALID
3252 * required property is not SCF_TYPE_ASTRING has more than one value.
3255 scf_tmpl_prop_required(const scf_prop_tmpl_t
*t
, uint8_t *out
)
3257 if (_read_single_boolean_from_pg(t
->prt_pg
, SCF_PROPERTY_TM_REQUIRED
,
3259 if (ismember(scf_error(), errors_server
)) {
3261 } else switch (scf_error()) {
3262 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3263 case SCF_ERROR_TYPE_MISMATCH
:
3264 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3267 case SCF_ERROR_NOT_FOUND
:
3271 case SCF_ERROR_INVALID_ARGUMENT
:
3272 case SCF_ERROR_NOT_SET
:
3283 * Returns -1 on failure. Sets scf_error():
3284 * SCF_ERROR_BACKEND_ACCESS
3285 * SCF_ERROR_CONNECTION_BROKEN
3287 * SCF_ERROR_HANDLE_DESTROYED
3288 * SCF_ERROR_INTERNAL
3289 * SCF_ERROR_NO_MEMORY
3290 * SCF_ERROR_NO_RESOURCES
3291 * SCF_ERROR_NOT_BOUND
3292 * SCF_ERROR_NOT_FOUND
3293 * Property doesn't exist or exists and has no value.
3294 * SCF_ERROR_INVALID_ARGUMENT
3295 * locale is too long to make a property name
3296 * SCF_ERROR_PERMISSION_DENIED
3297 * SCF_ERROR_TEMPLATE_INVALID
3298 * common_name property is not SCF_TYPE_ASTRING has more than one value.
3301 scf_tmpl_prop_common_name(const scf_prop_tmpl_t
*t
, const char *locale
,
3304 assert(out
!= NULL
);
3305 if ((*out
= _read_localized_astring_from_pg(t
->prt_pg
,
3306 SCF_PROPERTY_TM_COMMON_NAME_PREFIX
, locale
)) == NULL
)
3309 return (strlen(*out
));
3313 * Returns -1 on failure. Sets scf_error():
3314 * SCF_ERROR_BACKEND_ACCESS
3315 * SCF_ERROR_CONNECTION_BROKEN
3317 * SCF_ERROR_HANDLE_DESTROYED
3318 * SCF_ERROR_INTERNAL
3319 * SCF_ERROR_NO_MEMORY
3320 * SCF_ERROR_NO_RESOURCES
3321 * SCF_ERROR_NOT_BOUND
3322 * SCF_ERROR_NOT_FOUND
3323 * Property doesn't exist or exists and has no value.
3324 * SCF_ERROR_INVALID_ARGUMENT
3325 * locale is too long to make a property name
3326 * SCF_ERROR_PERMISSION_DENIED
3327 * SCF_ERROR_TEMPLATE_INVALID
3328 * description property is not SCF_TYPE_ASTRING has more than one value.
3331 scf_tmpl_prop_description(const scf_prop_tmpl_t
*t
, const char *locale
,
3334 assert(out
!= NULL
);
3335 if ((*out
= _read_localized_astring_from_pg(t
->prt_pg
,
3336 SCF_PROPERTY_TM_DESCRIPTION_PREFIX
, locale
)) == NULL
)
3339 return (strlen(*out
));
3343 * Returns -1 on failure. Sets scf_error():
3344 * SCF_ERROR_BACKEND_ACCESS
3345 * SCF_ERROR_CONNECTION_BROKEN
3347 * SCF_ERROR_HANDLE_DESTROYED
3348 * SCF_ERROR_INTERNAL
3349 * SCF_ERROR_NO_MEMORY
3350 * SCF_ERROR_NO_RESOURCES
3351 * SCF_ERROR_NOT_BOUND
3352 * SCF_ERROR_NOT_FOUND
3353 * Property doesn't exist or exists and has no value.
3354 * SCF_ERROR_INVALID_ARGUMENT
3355 * locale is too long to make a property name
3356 * SCF_ERROR_PERMISSION_DENIED
3357 * SCF_ERROR_TEMPLATE_INVALID
3358 * units property is not SCF_TYPE_ASTRING has more than one value.
3361 scf_tmpl_prop_units(const scf_prop_tmpl_t
*t
, const char *locale
, char **out
)
3363 assert(out
!= NULL
);
3364 if ((*out
= _read_localized_astring_from_pg(t
->prt_pg
,
3365 SCF_PROPERTY_TM_UNITS_PREFIX
, locale
)) == NULL
)
3368 return (strlen(*out
));
3372 * Returns -1 on failure. Sets scf_error():
3373 * SCF_ERROR_BACKEND_ACCESS
3374 * SCF_ERROR_CONNECTION_BROKEN
3376 * SCF_ERROR_HANDLE_DESTROYED
3377 * SCF_ERROR_INTERNAL
3378 * SCF_ERROR_NO_MEMORY
3379 * SCF_ERROR_NO_RESOURCES
3380 * SCF_ERROR_NOT_BOUND
3381 * SCF_ERROR_PERMISSION_DENIED
3382 * SCF_ERROR_TEMPLATE_INVALID
3383 * visibility property is not SCF_TYPE_ASTRING has more than one value.
3386 scf_tmpl_prop_visibility(const scf_prop_tmpl_t
*t
, uint8_t *out
)
3390 visibility
= _scf_read_single_astring_from_pg(t
->prt_pg
,
3391 SCF_PROPERTY_TM_VISIBILITY
);
3392 if (visibility
== NULL
) {
3393 if (ismember(scf_error(), errors_server
)) {
3395 } else switch (scf_error()) {
3396 /* prop doesn't exist we take the default value */
3397 case SCF_ERROR_NOT_FOUND
:
3398 *out
= SCF_TMPL_VISIBILITY_READWRITE
;
3401 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3402 case SCF_ERROR_TYPE_MISMATCH
:
3403 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3406 case SCF_ERROR_INVALID_ARGUMENT
:
3407 case SCF_ERROR_NOT_SET
:
3412 } else if (strcmp(visibility
, SCF_TM_VISIBILITY_READWRITE
) == 0) {
3413 *out
= SCF_TMPL_VISIBILITY_READWRITE
;
3414 } else if (strcmp(visibility
, SCF_TM_VISIBILITY_HIDDEN
) == 0) {
3415 *out
= SCF_TMPL_VISIBILITY_HIDDEN
;
3416 } else if (strcmp(visibility
, SCF_TM_VISIBILITY_READONLY
) == 0) {
3417 *out
= SCF_TMPL_VISIBILITY_READONLY
;
3420 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3429 * Return an allocated string containing the value that must be freed
3432 * On error set scf_error() _NO_MEMORY, or _NOT_SET (val has not been set
3436 _scf_value_get_as_string(scf_value_t
*val
)
3438 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
3439 char *buf
= malloc(sz
);
3442 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3443 } else if (scf_value_get_as_string(val
, buf
, sz
) == -1) {
3452 * Returns -1 on failure, sets scf_error() to:
3453 * SCF_ERROR_BACKEND_ACCESS
3454 * SCF_ERROR_CONNECTION_BROKEN
3456 * SCF_ERROR_HANDLE_DESTROYED
3457 * SCF_ERROR_INTERNAL
3458 * SCF_ERROR_NO_MEMORY
3459 * SCF_ERROR_NO_RESOURCES
3460 * SCF_ERROR_NOT_BOUND
3461 * SCF_ERROR_NOT_FOUND
3462 * SCF_ERROR_PERMISSION_DENIED
3463 * SCF_ERROR_TEMPLATE_INVALID
3466 scf_tmpl_prop_cardinality(const scf_prop_tmpl_t
*t
, uint64_t *min
,
3469 scf_value_t
*val_min
= NULL
;
3470 scf_value_t
*val_max
= NULL
;
3473 if (_read_single_value_from_pg(t
->prt_pg
,
3474 SCF_PROPERTY_TM_CARDINALITY_MIN
, &val_min
) == 0) {
3475 if (scf_value_get_count(val_min
, min
) < 0)
3478 if (scf_error() == SCF_ERROR_NOT_FOUND
)
3484 if (_read_single_value_from_pg(t
->prt_pg
,
3485 SCF_PROPERTY_TM_CARDINALITY_MAX
, &val_max
) == 0) {
3486 if (scf_value_get_count(val_max
, max
) < 0)
3489 if (scf_error() == SCF_ERROR_NOT_FOUND
)
3497 if (ismember(scf_error(), errors_server
)) {
3499 } else switch (scf_error()) {
3500 case SCF_ERROR_TYPE_MISMATCH
:
3501 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3502 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3505 case SCF_ERROR_NOT_FOUND
:
3506 case SCF_ERROR_TEMPLATE_INVALID
:
3510 case SCF_ERROR_NOT_SET
:
3511 case SCF_ERROR_INVALID_ARGUMENT
:
3518 scf_value_destroy(val_min
);
3519 scf_value_destroy(val_max
);
3525 * Returns -1 on failure. Sets scf_error():
3526 * SCF_ERROR_BACKEND_ACCESS
3527 * SCF_ERROR_CONNECTION_BROKEN
3529 * SCF_ERROR_HANDLE_DESTROYED
3530 * SCF_ERROR_INTERNAL
3531 * SCF_ERROR_NO_MEMORY
3532 * SCF_ERROR_NO_RESOURCES
3533 * SCF_ERROR_NOT_BOUND
3534 * SCF_ERROR_NOT_FOUND
3535 * Property doesn't exist or exists and has no value.
3536 * SCF_ERROR_PERMISSION_DENIED
3537 * SCF_ERROR_TEMPLATE_INVALID
3540 scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t
*t
, scf_values_t
*vals
)
3542 if (_read_astrings_values(t
->prt_pg
,
3543 SCF_PROPERTY_INTERNAL_SEPARATORS
, vals
) == NULL
) {
3544 if (ismember(scf_error(), errors_server
)) {
3546 } else switch (scf_error()) {
3547 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3548 case SCF_ERROR_TYPE_MISMATCH
:
3549 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3552 case SCF_ERROR_NOT_FOUND
:
3555 case SCF_ERROR_INVALID_ARGUMENT
:
3556 case SCF_ERROR_NOT_SET
:
3561 } else if (vals
->value_count
== 0) {
3562 /* property has no value */
3563 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3564 scf_values_destroy(vals
);
3572 * Returns -1 on failure. Sets scf_error():
3573 * SCF_ERROR_BACKEND_ACCESS
3574 * SCF_ERROR_CONNECTION_BROKEN
3576 * SCF_ERROR_HANDLE_DESTROYED
3577 * SCF_ERROR_INTERNAL
3578 * SCF_ERROR_NO_MEMORY
3579 * SCF_ERROR_NO_RESOURCES
3580 * SCF_ERROR_NOT_BOUND
3581 * SCF_ERROR_NOT_FOUND
3582 * Property doesn't exist or exists and has no value.
3583 * SCF_ERROR_PERMISSION_DENIED
3584 * SCF_ERROR_TEMPLATE_INVALID
3587 scf_tmpl_value_name_constraints(const scf_prop_tmpl_t
*t
,
3592 ret
= _read_astrings_values(t
->prt_pg
,
3593 SCF_PROPERTY_TM_CONSTRAINT_NAME
, vals
);
3596 if (ismember(scf_error(), errors_server
)) {
3598 } else switch (scf_error()) {
3599 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3600 case SCF_ERROR_TYPE_MISMATCH
:
3601 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3604 case SCF_ERROR_NOT_FOUND
:
3607 case SCF_ERROR_INVALID_ARGUMENT
:
3608 case SCF_ERROR_NOT_SET
:
3613 } else if (vals
->value_count
== 0) {
3614 /* property has no value */
3615 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3616 scf_values_destroy(vals
);
3624 * Returns NULL on failure. Sets scf_error():
3625 * Caller is responsible for freeing returned pointer after use.
3626 * SCF_ERROR_CONSTRAINT_VIOLATED
3627 * More tokens than the array size supplied.
3628 * SCF_ERROR_NO_MEMORY
3631 _separate_by_separator(char *string
, const char *sep
, char **array
, int size
)
3637 assert(array
!= NULL
);
3638 assert(string
!= NULL
);
3639 assert(sep
!= NULL
);
3642 str
= strdup(string
);
3644 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3648 if ((array
[n
] = strtok_r(str
, sep
, &lasts
)) == NULL
) {
3654 while ((token
= strtok_r(NULL
, sep
, &lasts
)) != NULL
) {
3668 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3673 * check if name is among values of CHOICES_INCLUDE_VALUES
3674 * return 0 if name is present, 1 name is not present, -1 on failure
3675 * SCF_ERROR_BACKEND_ACCESS
3676 * SCF_ERROR_CONNECTION_BROKEN
3678 * SCF_ERROR_HANDLE_DESTROYED
3679 * SCF_ERROR_INTERNAL
3680 * SCF_ERROR_NO_MEMORY
3681 * SCF_ERROR_NO_RESOURCES
3682 * SCF_ERROR_NOT_BOUND
3683 * SCF_ERROR_PERMISSION_DENIED
3684 * SCF_ERROR_TEMPLATE_INVALID
3687 _check_choices_include_values(scf_propertygroup_t
*pg
, const char *name
)
3693 if ((ret
= _read_astrings_values(pg
,
3694 SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES
, &vals
)) == NULL
) {
3695 if (ismember(scf_error(), errors_server
)) {
3697 } else switch (scf_error()) {
3698 case SCF_ERROR_NOT_FOUND
:
3701 case SCF_ERROR_TYPE_MISMATCH
:
3702 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3705 case SCF_ERROR_INVALID_ARGUMENT
:
3706 case SCF_ERROR_NOT_SET
:
3713 for (n
= 0; n
< vals
.value_count
; ++n
) {
3714 if (strcmp(name
, ret
[n
]) == 0) {
3719 scf_values_destroy(&vals
);
3724 scf_count_ranges_destroy(scf_count_ranges_t
*ranges
)
3729 ranges
->scr_num_ranges
= 0;
3730 free(ranges
->scr_min
);
3731 free(ranges
->scr_max
);
3732 ranges
->scr_min
= NULL
;
3733 ranges
->scr_max
= NULL
;
3737 scf_int_ranges_destroy(scf_int_ranges_t
*ranges
)
3742 ranges
->sir_num_ranges
= 0;
3743 free(ranges
->sir_min
);
3744 free(ranges
->sir_max
);
3745 ranges
->sir_min
= NULL
;
3746 ranges
->sir_max
= NULL
;
3750 * Returns -1 on failure. Sets scf_error():
3751 * SCF_ERROR_BACKEND_ACCESS
3752 * SCF_ERROR_CONNECTION_BROKEN
3753 * SCF_ERROR_CONSTRAINT_VIOLATED
3755 * SCF_ERROR_HANDLE_DESTROYED
3756 * SCF_ERROR_INTERNAL
3757 * SCF_ERROR_NO_MEMORY
3758 * SCF_ERROR_NO_RESOURCES
3759 * SCF_ERROR_NOT_BOUND
3760 * SCF_ERROR_NOT_FOUND
3761 * Property doesn't exist or exists and has no value.
3762 * SCF_ERROR_PERMISSION_DENIED
3763 * SCF_ERROR_TEMPLATE_INVALID
3766 _scf_tmpl_get_count_ranges(const scf_prop_tmpl_t
*t
, const char *prop
,
3767 scf_count_ranges_t
*ranges
)
3775 uint64_t *min
= NULL
;
3776 uint64_t *max
= NULL
;
3778 assert(ranges
!= NULL
);
3779 if ((ret
= _read_astrings_values(t
->prt_pg
, prop
, &vals
)) == NULL
)
3781 if (vals
.value_count
== 0) {
3782 /* range values are empty */
3783 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3787 min
= malloc(vals
.value_count
* sizeof (uint64_t));
3788 max
= malloc(vals
.value_count
* sizeof (uint64_t));
3789 if (min
== NULL
|| max
== NULL
) {
3790 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3793 for (i
= 0; i
< vals
.value_count
; ++i
) {
3794 /* min and max should be separated by a "," */
3795 if ((str
= _separate_by_separator(ret
[i
], ",", one_range
,
3799 min
[i
] = strtoull(one_range
[0], &endptr
, 10);
3800 if (errno
!= 0 || endptr
== one_range
[0] || *endptr
) {
3801 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3805 max
[i
] = strtoull(one_range
[1], &endptr
, 10);
3806 if (errno
!= 0 || endptr
== one_range
[1] || *endptr
) {
3807 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3810 if (min
[i
] > max
[i
]) {
3811 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3817 ranges
->scr_num_ranges
= vals
.value_count
;
3818 ranges
->scr_min
= min
;
3819 ranges
->scr_max
= max
;
3820 scf_values_destroy(&vals
);
3826 scf_values_destroy(&vals
);
3828 if (ismember(scf_error(), errors_server
)) {
3830 } else switch (scf_error()) {
3831 case SCF_ERROR_TYPE_MISMATCH
:
3832 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3835 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3836 case SCF_ERROR_NOT_FOUND
:
3839 case SCF_ERROR_INVALID_ARGUMENT
:
3840 case SCF_ERROR_NOT_SET
:
3849 * Returns -1 on failure. Sets scf_error():
3850 * SCF_ERROR_BACKEND_ACCESS
3851 * SCF_ERROR_CONNECTION_BROKEN
3852 * SCF_ERROR_CONSTRAINT_VIOLATED
3854 * SCF_ERROR_HANDLE_DESTROYED
3855 * SCF_ERROR_INTERNAL
3856 * SCF_ERROR_NO_MEMORY
3857 * SCF_ERROR_NO_RESOURCES
3858 * SCF_ERROR_NOT_BOUND
3859 * SCF_ERROR_NOT_FOUND
3860 * Property doesn't exist or exists and has no value.
3861 * SCF_ERROR_PERMISSION_DENIED
3862 * SCF_ERROR_TEMPLATE_INVALID
3865 _scf_tmpl_get_int_ranges(const scf_prop_tmpl_t
*t
, const char *prop
,
3866 scf_int_ranges_t
*ranges
)
3874 int64_t *min
= NULL
;
3875 int64_t *max
= NULL
;
3877 assert(ranges
!= NULL
);
3878 if ((ret
= _read_astrings_values(t
->prt_pg
, prop
, &vals
)) == NULL
)
3880 if (vals
.value_count
== 0) {
3881 /* range values are empty */
3882 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3886 min
= malloc(vals
.value_count
* sizeof (int64_t));
3887 max
= malloc(vals
.value_count
* sizeof (int64_t));
3888 if (min
== NULL
|| max
== NULL
) {
3889 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3892 while (n
< vals
.value_count
) {
3893 /* min and max should be separated by a "," */
3894 if ((str
= _separate_by_separator(ret
[n
], ",", one_range
, 2))
3898 min
[n
] = strtoll(one_range
[0], &endptr
, 10);
3899 if (errno
!= 0 || endptr
== one_range
[0] || *endptr
) {
3900 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3904 max
[n
] = strtoll(one_range
[1], &endptr
, 10);
3905 if (errno
!= 0 || endptr
== one_range
[1] || *endptr
) {
3906 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3909 if (min
[n
] > max
[n
]) {
3910 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3917 ranges
->sir_num_ranges
= vals
.value_count
;
3918 ranges
->sir_min
= min
;
3919 ranges
->sir_max
= max
;
3920 scf_values_destroy(&vals
);
3926 scf_values_destroy(&vals
);
3928 if (ismember(scf_error(), errors_server
)) {
3930 } else switch (scf_error()) {
3931 case SCF_ERROR_TYPE_MISMATCH
:
3932 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3935 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3936 case SCF_ERROR_NOT_FOUND
:
3937 case SCF_ERROR_TEMPLATE_INVALID
:
3940 case SCF_ERROR_INVALID_ARGUMENT
:
3941 case SCF_ERROR_NOT_SET
:
3950 * Returns -1 on failure. Sets scf_error():
3951 * SCF_ERROR_BACKEND_ACCESS
3952 * SCF_ERROR_CONNECTION_BROKEN
3953 * SCF_ERROR_CONSTRAINT_VIOLATED
3955 * SCF_ERROR_HANDLE_DESTROYED
3956 * SCF_ERROR_INTERNAL
3957 * SCF_ERROR_NO_MEMORY
3958 * SCF_ERROR_NO_RESOURCES
3959 * SCF_ERROR_NOT_BOUND
3960 * SCF_ERROR_NOT_FOUND
3961 * Property doesn't exist or exists and has no value.
3962 * SCF_ERROR_PERMISSION_DENIED
3963 * SCF_ERROR_TEMPLATE_INVALID
3966 scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t
*t
,
3967 scf_count_ranges_t
*ranges
)
3969 return (_scf_tmpl_get_count_ranges(t
, SCF_PROPERTY_TM_CONSTRAINT_RANGE
,
3974 scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t
*t
,
3975 scf_int_ranges_t
*ranges
)
3977 return (_scf_tmpl_get_int_ranges(t
, SCF_PROPERTY_TM_CONSTRAINT_RANGE
,
3982 scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t
*t
,
3983 scf_count_ranges_t
*ranges
)
3985 return (_scf_tmpl_get_count_ranges(t
, SCF_PROPERTY_TM_CHOICES_RANGE
,
3990 scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t
*t
,
3991 scf_int_ranges_t
*ranges
)
3993 return (_scf_tmpl_get_int_ranges(t
, SCF_PROPERTY_TM_CHOICES_RANGE
,
3998 * Returns -1 on failure. Sets scf_error():
3999 * SCF_ERROR_BACKEND_ACCESS
4000 * SCF_ERROR_CONNECTION_BROKEN
4002 * SCF_ERROR_HANDLE_DESTROYED
4003 * SCF_ERROR_INTERNAL
4004 * SCF_ERROR_NO_MEMORY
4005 * SCF_ERROR_NO_RESOURCES
4006 * SCF_ERROR_NOT_BOUND
4007 * SCF_ERROR_NOT_FOUND
4008 * Property doesn't exist or exists and has no value.
4009 * SCF_ERROR_PERMISSION_DENIED
4010 * SCF_ERROR_TEMPLATE_INVALID
4013 scf_tmpl_value_name_choices(const scf_prop_tmpl_t
*t
, scf_values_t
*vals
)
4015 int c_flag
= 0; /* have not read any value yet */
4019 /* First, look for explicitly declared choices. */
4020 if ((ret
= _read_astrings_values(t
->prt_pg
,
4021 SCF_PROPERTY_TM_CHOICES_NAME
, vals
)) != NULL
) {
4023 } else if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4027 /* Next, check for choices included by 'values'. */
4028 if ((r
= _check_choices_include_values(t
->prt_pg
, "values")) == 0) {
4029 /* read values_name */
4032 ret
= _append_astrings_values(t
->prt_pg
,
4033 SCF_PROPERTY_TM_VALUES_NAME
, vals
);
4036 ret
= _read_astrings_values(t
->prt_pg
,
4037 SCF_PROPERTY_TM_VALUES_NAME
, vals
);
4040 } else if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4043 } else if (r
== -1) {
4047 /* Finally check for choices included by 'constraints'. */
4048 if ((r
= _check_choices_include_values(t
->prt_pg
, "constraints")) ==
4050 /* read constraint_name */
4053 ret
= _append_astrings_values(t
->prt_pg
,
4054 SCF_PROPERTY_TM_CONSTRAINT_NAME
, vals
);
4057 ret
= _read_astrings_values(t
->prt_pg
,
4058 SCF_PROPERTY_TM_CONSTRAINT_NAME
, vals
);
4061 } else if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4064 } else if (r
== -1) {
4068 if (c_flag
== 0 || vals
->value_count
== 0) {
4069 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
4076 if (ismember(scf_error(), errors_server
)) {
4078 } else switch (scf_error()) {
4079 case SCF_ERROR_TYPE_MISMATCH
:
4080 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
4083 case SCF_ERROR_NOT_SET
:
4084 case SCF_ERROR_INVALID_ARGUMENT
:
4093 scf_values_destroy(scf_values_t
*vals
)
4096 char **items
= NULL
;
4102 str
= vals
->values_as_strings
;
4105 switch (vals
->value_type
) {
4106 case SCF_TYPE_BOOLEAN
:
4107 free(vals
->values
.v_boolean
);
4109 case SCF_TYPE_COUNT
:
4110 free(vals
->values
.v_count
);
4112 case SCF_TYPE_INTEGER
:
4113 free(vals
->values
.v_integer
);
4115 case SCF_TYPE_ASTRING
:
4116 items
= vals
->values
.v_astring
;
4119 case SCF_TYPE_USTRING
:
4120 items
= vals
->values
.v_ustring
;
4123 case SCF_TYPE_OPAQUE
:
4124 items
= vals
->values
.v_opaque
;
4128 free(vals
->values
.v_time
);
4134 for (i
= 0; i
< vals
->value_count
; ++i
) {
4140 vals
->value_count
= 0;
4146 * char *_make_value_name()
4148 * Construct the prefix for a value common name or value description property.
4149 * It takes the form:
4150 * value_<BASE32 name>_<common_name|description>_
4151 * This is then combined with a localized suffix by the caller to look
4152 * up the property in the repository:
4153 * value_<BASE32 name>_<common_name|description>_<lang>
4155 * Returns NULL on failure. Sets scf_error():
4156 * SCF_ERROR_INVALID_ARGUMENT
4157 * Name isn't short enough make a value name with.
4158 * SCF_ERROR_NO_MEMORY
4161 _make_value_name(char *desc_name
, const char *value
)
4164 char *encoded
= NULL
;
4165 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
4168 encoded
= malloc(sz
);
4169 if (name
== NULL
|| encoded
== NULL
) {
4170 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4176 if (scf_encode32(value
, strlen(value
), encoded
, sz
, NULL
,
4177 SCF_ENCODE32_PAD
) != 0) {
4178 /* Shouldn't happen. */
4182 (void) strlcpy(name
, SCF_PROPERTY_TM_VALUE_PREFIX
, sz
);
4184 if (strlcat(name
, encoded
, sz
) >= sz
) {
4185 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4191 if (strlcat(name
, "_", sz
) >= sz
) {
4192 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4198 if (strlcat(name
, desc_name
, sz
) >= sz
) {
4199 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4205 if (strlcat(name
, "_", sz
) >= sz
) {
4206 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4217 * ssize_t scf_tmpl_value_common_name()
4219 * Populates "out" with an allocated string containing the value's
4220 * common name. Returns the size of the string on successful return.
4221 * out must be freed with free() on successful return.
4223 * Returns -1 on failure, sets scf_error() to:
4224 * SCF_ERROR_BACKEND_ACCESS
4225 * SCF_ERROR_CONNECTION_BROKEN
4227 * Property group was deleted.
4228 * SCF_ERROR_HANDLE_DESTROYED
4229 * SCF_ERROR_INTERNAL
4230 * SCF_ERROR_INVALID_ARGUMENT
4231 * name not a valid property name
4232 * name and locale are too long to make a property name
4233 * SCF_ERROR_NO_MEMORY
4234 * SCF_ERROR_NO_RESOURCES
4235 * SCF_ERROR_NOT_BOUND
4236 * SCF_ERROR_NOT_FOUND
4237 * Property doesn't exist or exists and has no value.
4238 * SCF_ERROR_PERMISSION_DENIED
4239 * SCF_ERROR_TEMPLATE_INVALID
4240 * property is not SCF_TYPE_ASTRING has more than one value.
4243 scf_tmpl_value_common_name(const scf_prop_tmpl_t
*t
, const char *locale
,
4244 const char *value
, char **out
)
4246 char *value_name
= NULL
;
4248 value_name
= _make_value_name("common_name", value
);
4249 if (value_name
== NULL
)
4252 *out
= _read_localized_astring_from_pg(t
->prt_pg
, value_name
, locale
);
4259 return (strlen(*out
));
4263 * ssize_t scf_tmpl_value_description()
4265 * Populates "out" with an allocated string containing the value's
4266 * description. Returns the size of the string on successful return.
4267 * out must be freed with free() on successful return.
4269 * Returns -1 on failure, sets scf_error() to:
4270 * SCF_ERROR_BACKEND_ACCESS
4271 * SCF_ERROR_CONNECTION_BROKEN
4273 * Property group was deleted.
4274 * SCF_ERROR_HANDLE_DESTROYED
4275 * SCF_ERROR_INTERNAL
4276 * SCF_ERROR_INVALID_ARGUMENT
4277 * name not a valid property name
4278 * name and locale are too long to make a property name
4279 * SCF_ERROR_NO_MEMORY
4280 * SCF_ERROR_NO_RESOURCES
4281 * SCF_ERROR_NOT_BOUND
4282 * SCF_ERROR_NOT_FOUND
4283 * Property doesn't exist or exists and has no value.
4284 * SCF_ERROR_PERMISSION_DENIED
4285 * SCF_ERROR_TEMPLATE_INVALID
4286 * property is not SCF_TYPE_ASTRING has more than one value.
4289 scf_tmpl_value_description(const scf_prop_tmpl_t
*t
, const char *locale
,
4290 const char *value
, char **out
)
4292 char *value_name
= NULL
;
4294 value_name
= _make_value_name("description", value
);
4295 if (value_name
== NULL
)
4299 *out
= _read_localized_astring_from_pg(t
->prt_pg
, value_name
, locale
);
4306 return (strlen(*out
));
4310 * Templates error messages format, in human readable form.
4311 * Each line is one error item:
4313 * prefix error message
4314 * FMRI="err->te_errs->tes_fmri"
4315 * Property group="err->te_pg_name"
4316 * Property name="err->te_prop_name"
4317 * expected value 1="err->te_ev1"
4318 * expected value 2="err->te_ev2"
4319 * actual value="err->te_actual"
4320 * Tempalte source="err->te_tmpl_fmri"
4321 * pg_pattern name="err->tmpl_pg_name"
4322 * pg_pattern type="err->tmpl_pg_type"
4323 * prop_pattern name="err->tmpl_prop_name"
4324 * prop_pattern type="err->tmpl_prop_type"
4326 * To add a new error type, include scf_tmpl_error_type_t in libscf.h
4327 * add one entry in em_desc[], and update the functions pointed by the
4328 * _tmpl_error_access array with the new error code. Also, update the
4329 * scf_tmpl_error_* functions to provide access to desired
4330 * scf_tmpl_error_t fields.
4332 * To add a new error item, add a new field to scf_tmpl_error_t, a new field
4333 * in _scf_tmpl_error_desc or a new non-error-dependent string, add a new entry
4334 * in _tmpl_error_access array and create the appropriate get_val, get_desc
4337 * Changes to both the validation logic and the error types and items must
4338 * be coordinated with the code in svccfg to ensure both libscf and svccfg's
4339 * manifest validation validate the same things.
4343 * Container for all template errors on a validated object.
4345 struct scf_tmpl_errors
{
4348 scf_tmpl_error_t
**tes_errs
;
4350 const char *tes_fmri
;
4351 const char *tes_prefix
;
4352 int tes_flag
; /* if set, scf_tmpl_error_destroy */
4353 /* will free strings in tes_errs */
4357 * Templates error-dependent labels
4359 struct _scf_tmpl_error_desc
{
4363 const char *em_actual
;
4367 * This array MUST be kept in synch with the template error definition of
4368 * scf_tmpl_error_type_t in libscf.h
4370 static struct _scf_tmpl_error_desc em_desc
[] = {
4371 /* SCF_TERR_MISSING_PG */
4372 { "Required property group missing", "Name of missing property group",
4373 "Type of missing property group", NULL
},
4374 /* SCF_TERR_WRONG_PG_TYPE */
4375 { "Property group has bad type", "Specified type", NULL
,
4377 /* SCF_TERR_MISSING_PROP */
4378 { "Required property missing", "Name of missing property", NULL
, NULL
},
4379 /* SCF_TERR_WRONG_PROP_TYPE */
4380 { "Property has bad type", "Specified property type", NULL
,
4381 "Actual property type" },
4382 /* SCF_TERR_CARDINALITY_VIOLATION */
4383 { "Number of property values violates cardinality restriction",
4384 "Cardinality minimum", "Cardinality maximum",
4385 "Actual number of values" },
4386 /* SCF_TERR_VALUE_CONSTRAINT_VIOLATED */
4387 { "Property has illegal value", NULL
, NULL
, "Illegal value" },
4388 /* SCF_TERR_RANGE_VIOLATION */
4389 { "Property value is out of range", NULL
, NULL
, "Actual value" },
4390 /* SCF_TERR_PG_REDEFINE */
4391 { "Instance redefines pg_pattern", "Instance pg_pattern name",
4392 "Instance pg_pattern type", NULL
},
4393 /* SCF_TERR_PROP_TYPE_MISMATCH */
4394 { "Property type and value type mismatch", NULL
, NULL
, "Value type" },
4395 /* SCF_TERR_VALUE_OUT_OF_RANGE */
4396 { "Value is out of range", NULL
, NULL
, "Value" },
4397 /* SCF_TERR_INVALID_VALUE */
4398 { "Value is not valid", NULL
, NULL
, "Value" },
4399 /* SCF_TERR_PG_PATTERN_CONFLICT */
4400 { "Conflicting pg_pattern specifications", "Template source",
4401 "pg_pattern name", "pg_pattern type" },
4402 /* SCF_TERR_PROP_PATTERN_CONFLICT */
4403 { "Conflicting prop_pattern specifications", "Template source",
4404 "prop_pattern name", "prop_pattern type" },
4405 /* SCF_TERR_GENERAL_REDEFINE */
4406 { "Service or instance pg_pattern redefines a global or restarter "
4407 "pg_pattern", "Template source", "pg_pattern name",
4408 "pg_pattern type" },
4409 /* SCF_TERR_INCLUDE_VALUES */
4410 { "Missing constraints or values for include_values element",
4411 "include_values type", NULL
, NULL
},
4412 /* SCF_TERR_PG_PATTERN_INCOMPLETE */
4413 { "Required pg_pattern is missing a name or type attribute",
4415 /* SCF_TERR_PROP_PATTERN_INCOMPLETE */
4416 { "Required prop_pattern is missing a type attribute",
4421 * Templates non error-dependent labels
4423 static const char *em_fmri
= "FMRI";
4424 static const char *em_pg_name
= "Property group";
4425 static const char *em_prop_name
= "Property name";
4426 static const char *em_tmpl_fmri
= "Template source";
4427 static const char *em_tmpl_pg_name
= "pg_pattern name";
4428 static const char *em_tmpl_pg_type
= "pg_pattern type";
4429 static const char *em_tmpl_prop_name
= "prop_pattern name";
4430 static const char *em_tmpl_prop_type
= "prop_pattern type";
4433 _get_fmri_desc(scf_tmpl_error_t
*err
)
4435 switch (err
->te_type
) {
4436 case SCF_TERR_MISSING_PG
:
4437 case SCF_TERR_WRONG_PG_TYPE
:
4438 case SCF_TERR_MISSING_PROP
:
4439 case SCF_TERR_WRONG_PROP_TYPE
:
4440 case SCF_TERR_CARDINALITY_VIOLATION
:
4441 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4442 case SCF_TERR_RANGE_VIOLATION
:
4443 case SCF_TERR_PG_REDEFINE
:
4444 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4445 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4446 case SCF_TERR_INCLUDE_VALUES
:
4447 return (dgettext(TEXT_DOMAIN
, em_fmri
));
4448 case SCF_TERR_PROP_TYPE_MISMATCH
:
4449 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4450 case SCF_TERR_INVALID_VALUE
:
4451 case SCF_TERR_PG_PATTERN_CONFLICT
:
4452 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4453 case SCF_TERR_GENERAL_REDEFINE
:
4460 _get_pg_name_desc(scf_tmpl_error_t
*err
)
4462 switch (err
->te_type
) {
4463 case SCF_TERR_WRONG_PG_TYPE
:
4464 case SCF_TERR_MISSING_PROP
:
4465 case SCF_TERR_WRONG_PROP_TYPE
:
4466 case SCF_TERR_CARDINALITY_VIOLATION
:
4467 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4468 case SCF_TERR_RANGE_VIOLATION
:
4469 return (dgettext(TEXT_DOMAIN
, em_pg_name
));
4470 case SCF_TERR_MISSING_PG
:
4471 case SCF_TERR_PG_REDEFINE
:
4472 case SCF_TERR_PROP_TYPE_MISMATCH
:
4473 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4474 case SCF_TERR_INVALID_VALUE
:
4475 case SCF_TERR_PG_PATTERN_CONFLICT
:
4476 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4477 case SCF_TERR_GENERAL_REDEFINE
:
4478 case SCF_TERR_INCLUDE_VALUES
:
4479 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4480 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4487 _get_prop_name_desc(scf_tmpl_error_t
*err
)
4489 switch (err
->te_type
) {
4490 case SCF_TERR_WRONG_PROP_TYPE
:
4491 case SCF_TERR_CARDINALITY_VIOLATION
:
4492 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4493 case SCF_TERR_RANGE_VIOLATION
:
4494 return (dgettext(TEXT_DOMAIN
, em_prop_name
));
4495 case SCF_TERR_MISSING_PG
:
4496 case SCF_TERR_WRONG_PG_TYPE
:
4497 case SCF_TERR_MISSING_PROP
:
4498 case SCF_TERR_PG_REDEFINE
:
4499 case SCF_TERR_PROP_TYPE_MISMATCH
:
4500 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4501 case SCF_TERR_INVALID_VALUE
:
4502 case SCF_TERR_PG_PATTERN_CONFLICT
:
4503 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4504 case SCF_TERR_GENERAL_REDEFINE
:
4505 case SCF_TERR_INCLUDE_VALUES
:
4506 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4507 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4514 _get_ev1_desc(scf_tmpl_error_t
*err
)
4516 switch (err
->te_type
) {
4517 case SCF_TERR_MISSING_PG
:
4518 case SCF_TERR_WRONG_PG_TYPE
:
4519 case SCF_TERR_MISSING_PROP
:
4520 case SCF_TERR_WRONG_PROP_TYPE
:
4521 case SCF_TERR_CARDINALITY_VIOLATION
:
4522 case SCF_TERR_RANGE_VIOLATION
:
4523 case SCF_TERR_PG_REDEFINE
:
4524 case SCF_TERR_PG_PATTERN_CONFLICT
:
4525 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4526 case SCF_TERR_GENERAL_REDEFINE
:
4527 case SCF_TERR_INCLUDE_VALUES
:
4528 return (dgettext(TEXT_DOMAIN
, em_desc
[err
->te_type
].em_ev1
));
4529 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4530 case SCF_TERR_PROP_TYPE_MISMATCH
:
4531 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4532 case SCF_TERR_INVALID_VALUE
:
4533 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4534 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4541 _get_ev2_desc(scf_tmpl_error_t
*err
)
4543 switch (err
->te_type
) {
4544 case SCF_TERR_MISSING_PG
:
4545 case SCF_TERR_CARDINALITY_VIOLATION
:
4546 case SCF_TERR_RANGE_VIOLATION
:
4547 case SCF_TERR_PG_REDEFINE
:
4548 case SCF_TERR_PG_PATTERN_CONFLICT
:
4549 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4550 case SCF_TERR_GENERAL_REDEFINE
:
4551 return (dgettext(TEXT_DOMAIN
, em_desc
[err
->te_type
].em_ev2
));
4552 case SCF_TERR_WRONG_PG_TYPE
:
4553 case SCF_TERR_MISSING_PROP
:
4554 case SCF_TERR_WRONG_PROP_TYPE
:
4555 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4556 case SCF_TERR_PROP_TYPE_MISMATCH
:
4557 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4558 case SCF_TERR_INVALID_VALUE
:
4559 case SCF_TERR_INCLUDE_VALUES
:
4560 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4561 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4568 _get_actual_desc(scf_tmpl_error_t
*err
)
4570 switch (err
->te_type
) {
4571 case SCF_TERR_MISSING_PG
:
4572 case SCF_TERR_WRONG_PG_TYPE
:
4573 case SCF_TERR_WRONG_PROP_TYPE
:
4574 case SCF_TERR_CARDINALITY_VIOLATION
:
4575 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4576 case SCF_TERR_RANGE_VIOLATION
:
4577 case SCF_TERR_PROP_TYPE_MISMATCH
:
4578 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4579 case SCF_TERR_INVALID_VALUE
:
4580 case SCF_TERR_PG_PATTERN_CONFLICT
:
4581 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4582 case SCF_TERR_GENERAL_REDEFINE
:
4583 case SCF_TERR_INCLUDE_VALUES
:
4584 return (dgettext(TEXT_DOMAIN
,
4585 em_desc
[err
->te_type
].em_actual
));
4586 case SCF_TERR_MISSING_PROP
:
4587 case SCF_TERR_PG_REDEFINE
:
4588 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4589 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4596 _get_tmpl_fmri_desc(scf_tmpl_error_t
*err
)
4598 switch (err
->te_type
) {
4599 case SCF_TERR_MISSING_PG
:
4600 case SCF_TERR_WRONG_PG_TYPE
:
4601 case SCF_TERR_MISSING_PROP
:
4602 case SCF_TERR_WRONG_PROP_TYPE
:
4603 case SCF_TERR_CARDINALITY_VIOLATION
:
4604 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4605 case SCF_TERR_RANGE_VIOLATION
:
4606 case SCF_TERR_PG_REDEFINE
:
4607 case SCF_TERR_PROP_TYPE_MISMATCH
:
4608 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4609 case SCF_TERR_INVALID_VALUE
:
4610 case SCF_TERR_PG_PATTERN_CONFLICT
:
4611 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4612 case SCF_TERR_GENERAL_REDEFINE
:
4613 case SCF_TERR_INCLUDE_VALUES
:
4614 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4615 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4616 return (dgettext(TEXT_DOMAIN
, em_tmpl_fmri
));
4623 _get_tmpl_pg_name_desc(scf_tmpl_error_t
*err
)
4625 switch (err
->te_type
) {
4626 case SCF_TERR_MISSING_PG
:
4627 case SCF_TERR_WRONG_PG_TYPE
:
4628 case SCF_TERR_MISSING_PROP
:
4629 case SCF_TERR_WRONG_PROP_TYPE
:
4630 case SCF_TERR_CARDINALITY_VIOLATION
:
4631 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4632 case SCF_TERR_RANGE_VIOLATION
:
4633 case SCF_TERR_PG_REDEFINE
:
4634 case SCF_TERR_PROP_TYPE_MISMATCH
:
4635 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4636 case SCF_TERR_INVALID_VALUE
:
4637 case SCF_TERR_PG_PATTERN_CONFLICT
:
4638 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4639 case SCF_TERR_GENERAL_REDEFINE
:
4640 case SCF_TERR_INCLUDE_VALUES
:
4641 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4642 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4643 return (dgettext(TEXT_DOMAIN
, em_tmpl_pg_name
));
4650 _get_tmpl_pg_type_desc(scf_tmpl_error_t
*err
)
4652 switch (err
->te_type
) {
4653 case SCF_TERR_MISSING_PG
:
4654 case SCF_TERR_WRONG_PG_TYPE
:
4655 case SCF_TERR_MISSING_PROP
:
4656 case SCF_TERR_WRONG_PROP_TYPE
:
4657 case SCF_TERR_CARDINALITY_VIOLATION
:
4658 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4659 case SCF_TERR_RANGE_VIOLATION
:
4660 case SCF_TERR_PG_REDEFINE
:
4661 case SCF_TERR_PROP_TYPE_MISMATCH
:
4662 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4663 case SCF_TERR_INVALID_VALUE
:
4664 case SCF_TERR_PG_PATTERN_CONFLICT
:
4665 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4666 case SCF_TERR_GENERAL_REDEFINE
:
4667 case SCF_TERR_INCLUDE_VALUES
:
4668 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4669 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4670 return (dgettext(TEXT_DOMAIN
, em_tmpl_pg_type
));
4677 _get_tmpl_prop_name_desc(scf_tmpl_error_t
*err
)
4679 switch (err
->te_type
) {
4680 case SCF_TERR_MISSING_PROP
:
4681 case SCF_TERR_WRONG_PROP_TYPE
:
4682 case SCF_TERR_CARDINALITY_VIOLATION
:
4683 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4684 case SCF_TERR_RANGE_VIOLATION
:
4685 case SCF_TERR_PROP_TYPE_MISMATCH
:
4686 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4687 case SCF_TERR_INVALID_VALUE
:
4688 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4689 case SCF_TERR_INCLUDE_VALUES
:
4690 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4691 return (dgettext(TEXT_DOMAIN
, em_tmpl_prop_name
));
4692 case SCF_TERR_MISSING_PG
:
4693 case SCF_TERR_WRONG_PG_TYPE
:
4694 case SCF_TERR_PG_REDEFINE
:
4695 case SCF_TERR_PG_PATTERN_CONFLICT
:
4696 case SCF_TERR_GENERAL_REDEFINE
:
4697 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4704 _get_tmpl_prop_type_desc(scf_tmpl_error_t
*err
)
4706 switch (err
->te_type
) {
4707 case SCF_TERR_MISSING_PROP
:
4708 case SCF_TERR_WRONG_PROP_TYPE
:
4709 case SCF_TERR_CARDINALITY_VIOLATION
:
4710 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4711 case SCF_TERR_RANGE_VIOLATION
:
4712 case SCF_TERR_PROP_TYPE_MISMATCH
:
4713 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4714 case SCF_TERR_INVALID_VALUE
:
4715 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4716 case SCF_TERR_INCLUDE_VALUES
:
4717 return (dgettext(TEXT_DOMAIN
, em_tmpl_prop_type
));
4718 case SCF_TERR_MISSING_PG
:
4719 case SCF_TERR_WRONG_PG_TYPE
:
4720 case SCF_TERR_PG_REDEFINE
:
4721 case SCF_TERR_PG_PATTERN_CONFLICT
:
4722 case SCF_TERR_GENERAL_REDEFINE
:
4723 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4724 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4731 _get_fmri_val(scf_tmpl_error_t
*err
)
4733 assert(err
!= NULL
&& err
->te_errs
!= NULL
&&
4734 err
->te_errs
->tes_fmri
!= NULL
);
4735 return (err
->te_errs
->tes_fmri
);
4739 _get_pg_name_val(scf_tmpl_error_t
*err
)
4741 assert(err
!= NULL
);
4742 return (err
->te_pg_name
);
4746 _get_prop_name_val(scf_tmpl_error_t
*err
)
4748 assert(err
!= NULL
);
4749 return (err
->te_prop_name
);
4753 _get_ev1_val(scf_tmpl_error_t
*err
)
4755 assert(err
!= NULL
);
4756 return (err
->te_ev1
);
4760 _get_ev2_val(scf_tmpl_error_t
*err
)
4762 assert(err
!= NULL
);
4763 return (err
->te_ev2
);
4767 _get_actual_val(scf_tmpl_error_t
*err
)
4769 assert(err
!= NULL
);
4770 return (err
->te_actual
);
4774 _get_tmpl_fmri_val(scf_tmpl_error_t
*err
)
4776 assert(err
!= NULL
);
4777 return (err
->te_tmpl_fmri
);
4781 _get_tmpl_pg_name_val(scf_tmpl_error_t
*err
)
4783 assert(err
!= NULL
);
4784 return (err
->te_tmpl_pg_name
);
4788 _get_tmpl_pg_type_val(scf_tmpl_error_t
*err
)
4790 assert(err
!= NULL
);
4791 return (err
->te_tmpl_pg_type
);
4795 _get_tmpl_prop_name_val(scf_tmpl_error_t
*err
)
4797 assert(err
!= NULL
);
4798 return (err
->te_tmpl_prop_name
);
4802 _get_tmpl_prop_type_val(scf_tmpl_error_t
*err
)
4804 assert(err
!= NULL
);
4805 return (err
->te_tmpl_prop_type
);
4809 * Templates error item retrival functions
4811 typedef const char *(*get_em
)(scf_tmpl_error_t
*);
4814 * if new items (lines) are added to the templates error messages,
4815 * new entries in this array (and new fuctions) will be required.
4817 static struct _tmpl_error_access
{
4820 } _tmpl_error_items
[] = {
4821 { (get_em
)_get_fmri_desc
, (get_em
)_get_fmri_val
},
4822 { (get_em
)_get_pg_name_desc
, (get_em
)_get_pg_name_val
},
4823 { (get_em
)_get_prop_name_desc
, (get_em
)_get_prop_name_val
},
4824 { (get_em
)_get_ev1_desc
, (get_em
)_get_ev1_val
},
4825 { (get_em
)_get_ev2_desc
, (get_em
)_get_ev2_val
},
4826 { (get_em
)_get_actual_desc
, (get_em
)_get_actual_val
},
4827 { (get_em
)_get_tmpl_fmri_desc
, (get_em
)_get_tmpl_fmri_val
},
4828 { (get_em
)_get_tmpl_pg_name_desc
, (get_em
)_get_tmpl_pg_name_val
},
4829 { (get_em
)_get_tmpl_pg_type_desc
, (get_em
)_get_tmpl_pg_type_val
},
4830 { (get_em
)_get_tmpl_prop_name_desc
, (get_em
)_get_tmpl_prop_name_val
},
4831 { (get_em
)_get_tmpl_prop_type_desc
, (get_em
)_get_tmpl_prop_type_val
},
4836 * Allocate a new scf_tmpl_error_t and add it to the errs list provided.
4837 * Returns NULL on failure. Sets scf_error():
4838 * SCF_ERROR_NO_MEMORY
4840 static scf_tmpl_error_t
*
4841 _create_error(scf_tmpl_errors_t
*errs
)
4843 scf_tmpl_error_t
*ret
;
4844 scf_tmpl_error_t
**saved_errs
;
4846 assert(errs
!= NULL
);
4847 ret
= calloc(1, sizeof (scf_tmpl_error_t
));
4849 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4853 ret
->te_errs
= errs
;
4855 assert(errs
->tes_num_errs
<= errs
->tes_errs_size
);
4856 if (errs
->tes_num_errs
== errs
->tes_errs_size
) {
4857 /* Time to grow the pointer array. */
4858 saved_errs
= errs
->tes_errs
;
4859 errs
->tes_errs
= calloc(2 * errs
->tes_errs_size
,
4860 sizeof (scf_tmpl_error_t
*));
4861 if (errs
->tes_errs
== NULL
) {
4862 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4863 errs
->tes_errs
= saved_errs
;
4867 (void) memcpy(errs
->tes_errs
, saved_errs
, errs
->tes_errs_size
*
4868 sizeof (scf_tmpl_error_t
*));
4869 errs
->tes_errs_size
= 2 * errs
->tes_errs_size
;
4873 errs
->tes_errs
[errs
->tes_num_errs
] = ret
;
4874 errs
->tes_num_errs
++;
4881 * If destroy_strings is set, scf_tmpl_errors_destroy will free the
4882 * strings in scf_tmpl_error_t entries.
4884 * Returns NULL on failure. Sets scf_error():
4885 * SCF_ERROR_NO_MEMORY
4888 _scf_create_errors(const char *fmri
, int destroy_strings
)
4890 scf_tmpl_errors_t
*ret
;
4893 assert(fmri
!= NULL
);
4895 ret
= calloc(1, sizeof (scf_tmpl_errors_t
));
4897 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4902 ret
->tes_num_errs
= 0;
4903 if ((ret
->tes_fmri
= strdup(fmri
)) == NULL
) {
4904 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4909 ret
->tes_prefix
= strdup("");
4910 if (ret
->tes_prefix
== NULL
) {
4911 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4912 free((char *)ret
->tes_fmri
);
4916 ret
->tes_flag
= destroy_strings
;
4918 /* Make space for a few errors. */
4919 ret
->tes_errs
= calloc(errs_size
, sizeof (scf_tmpl_error_t
*));
4920 if (ret
->tes_errs
== NULL
) {
4921 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4922 free((char *)ret
->tes_fmri
);
4923 free((char *)ret
->tes_prefix
);
4927 ret
->tes_errs_size
= errs_size
;
4933 * return 0 on success, if fails set scf_error() to:
4935 * SCF_ERROR_NO_MEMORY
4938 _scf_tmpl_error_set_prefix(scf_tmpl_errors_t
*errs
, const char *prefix
)
4940 free((void *) errs
->tes_prefix
);
4942 errs
->tes_prefix
= strdup("");
4944 errs
->tes_prefix
= strdup(prefix
);
4945 if (errs
->tes_prefix
== NULL
) {
4946 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4954 * Returns -1 on failure. Sets scf_error():
4955 * SCF_ERROR_NO_MEMORY
4958 _scf_tmpl_add_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
4959 const char *pg_name
, const char *prop_name
,
4960 const char *ev1
, const char *ev2
, const char *actual
,
4961 const char *tmpl_fmri
, const char *tmpl_pg_name
, const char *tmpl_pg_type
,
4962 const char *tmpl_prop_name
, const char *tmpl_prop_type
)
4964 scf_tmpl_error_t
*err
;
4966 assert(errs
!= NULL
);
4967 assert(tmpl_fmri
!= NULL
);
4969 err
= _create_error(errs
);
4973 err
->te_type
= type
;
4974 err
->te_pg_name
= pg_name
;
4975 err
->te_prop_name
= prop_name
;
4978 err
->te_actual
= actual
;
4979 err
->te_tmpl_fmri
= tmpl_fmri
;
4980 err
->te_tmpl_pg_name
= tmpl_pg_name
;
4981 err
->te_tmpl_pg_type
= tmpl_pg_type
;
4982 err
->te_tmpl_prop_name
= tmpl_prop_name
;
4983 err
->te_tmpl_prop_type
= tmpl_prop_type
;
4989 * returns an allocated string that must be freed with free()
4990 * string contains converted 64-bit integer value
4991 * flag set for signed values
4992 * if fails return NULL and set scf_error() to:
4993 * SCF_ERROR_NO_MEMORY
4996 _val_to_string(uint64_t val
, int flag
)
4998 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
5003 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5008 (void) snprintf(buf
, sz
, "%" PRIu64
, val
);
5010 (void) snprintf(buf
, sz
, "%" PRIi64
, (int64_t)val
);
5016 * return 0 on success, -1 on failure.
5017 * set scf_error() to:
5018 * SCF_ERROR_BACKEND_ACCESS
5019 * SCF_ERROR_CONNECTION_BROKEN
5021 * SCF_ERROR_HANDLE_DESTROYED
5022 * SCF_ERROR_INTERNAL
5023 * SCF_ERROR_NO_MEMORY
5024 * SCF_ERROR_NO_RESOURCES
5025 * SCF_ERROR_NOT_BOUND
5026 * SCF_ERROR_PERMISSION_DENIED
5027 * SCF_ERROR_TEMPLATE_INVALID
5030 _add_tmpl_missing_pg_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
)
5034 char *t_fmri
= NULL
;
5035 char *t_pg_name
= NULL
;
5036 char *t_pg_type
= NULL
;
5038 if ((t_fmri
= _scf_tmpl_get_fmri(t
)) == NULL
)
5040 if (scf_tmpl_pg_name(t
, &t_pg_name
) == -1) {
5043 if (scf_tmpl_pg_type(t
, &t_pg_type
) == -1) {
5046 if ((ev1
= strdup(t_pg_name
)) == NULL
) {
5047 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5050 if ((ev2
= strdup(t_pg_type
)) == NULL
) {
5051 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5055 return (_scf_tmpl_add_error(errs
, SCF_TERR_MISSING_PG
, NULL
, NULL
, ev1
,
5056 ev2
, NULL
, t_fmri
, t_pg_name
, t_pg_type
, NULL
, NULL
));
5067 * return 0 on success, -1 on failure.
5068 * set scf_error() to:
5069 * SCF_ERROR_BACKEND_ACCESS
5070 * SCF_ERROR_CONNECTION_BROKEN
5072 * SCF_ERROR_HANDLE_DESTROYED
5073 * SCF_ERROR_INTERNAL
5074 * SCF_ERROR_NO_MEMORY
5075 * SCF_ERROR_NO_RESOURCES
5076 * SCF_ERROR_NOT_BOUND
5077 * SCF_ERROR_PERMISSION_DENIED
5078 * SCF_ERROR_TEMPLATE_INVALID
5081 _add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
,
5082 scf_propertygroup_t
*pg
)
5084 char *pg_name
= NULL
;
5086 char *actual
= NULL
;
5087 char *t_fmri
= NULL
;
5088 char *t_pg_name
= NULL
;
5089 char *t_pg_type
= NULL
;
5091 if ((t_fmri
= _scf_tmpl_get_fmri(t
)) == NULL
)
5093 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5095 if ((actual
= _scf_get_pg_type(pg
)) == NULL
)
5097 if (scf_tmpl_pg_name(t
, &t_pg_name
) == -1) {
5100 if (scf_tmpl_pg_type(t
, &t_pg_type
) == -1) {
5103 if ((ev1
= strdup(t_pg_type
)) == NULL
) {
5104 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5108 return (_scf_tmpl_add_error(errs
, SCF_TERR_WRONG_PG_TYPE
, pg_name
, NULL
,
5109 ev1
, NULL
, actual
, t_fmri
, t_pg_name
, t_pg_type
, NULL
, NULL
));
5121 * return 0 on success, -1 on failure.
5122 * set scf_error() to:
5123 * SCF_ERROR_BACKEND_ACCESS
5124 * SCF_ERROR_CONNECTION_BROKEN
5126 * SCF_ERROR_HANDLE_DESTROYED
5127 * SCF_ERROR_INTERNAL
5128 * SCF_ERROR_NO_MEMORY
5129 * SCF_ERROR_NO_RESOURCES
5130 * SCF_ERROR_NOT_BOUND
5131 * SCF_ERROR_PERMISSION_DENIED
5132 * SCF_ERROR_TEMPLATE_INVALID
5135 _add_tmpl_missing_prop_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
,
5136 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
)
5138 char *pg_name
= NULL
;
5140 char *t_fmri
= NULL
;
5141 char *t_pg_name
= NULL
;
5142 char *t_pg_type
= NULL
;
5143 char *t_prop_name
= NULL
;
5144 char *t_prop_type
= NULL
;
5146 if ((t_fmri
= _scf_tmpl_get_fmri(t
)) == NULL
)
5148 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5150 if (scf_tmpl_pg_name(t
, &t_pg_name
) == -1) {
5153 if (scf_tmpl_pg_type(t
, &t_pg_type
) == -1) {
5156 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5159 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5160 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5163 } else if (t_prop_type
== NULL
) {
5166 if (t_prop_type
== NULL
)
5167 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5168 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5171 if ((ev1
= strdup(t_prop_name
)) == NULL
) {
5172 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5176 return (_scf_tmpl_add_error(errs
, SCF_TERR_MISSING_PROP
, pg_name
, NULL
,
5177 ev1
, NULL
, NULL
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
,
5191 * return 0 on success, -1 on failure.
5192 * set scf_error() to:
5193 * SCF_ERROR_BACKEND_ACCESS
5194 * SCF_ERROR_CONNECTION_BROKEN
5196 * SCF_ERROR_HANDLE_DESTROYED
5197 * SCF_ERROR_INTERNAL
5198 * SCF_ERROR_NO_MEMORY
5199 * SCF_ERROR_NO_RESOURCES
5200 * SCF_ERROR_NOT_BOUND
5201 * SCF_ERROR_PERMISSION_DENIED
5202 * SCF_ERROR_TEMPLATE_INVALID
5205 _add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t
*errs
,
5206 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
)
5208 char *pg_name
= NULL
;
5209 char *prop_name
= NULL
;
5211 char *actual
= NULL
;
5212 char *t_fmri
= NULL
;
5213 char *t_pg_name
= NULL
;
5214 char *t_pg_type
= NULL
;
5215 char *t_prop_name
= NULL
;
5216 char *t_prop_type
= NULL
;
5218 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5220 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5222 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5224 if ((actual
= _scf_get_prop_type(prop
)) == NULL
)
5226 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5229 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5232 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5235 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5236 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5239 } else if (t_prop_type
== NULL
) {
5242 if (t_prop_type
== NULL
)
5243 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5244 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5247 if ((ev1
= strdup(t_prop_type
)) == NULL
) {
5248 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5252 return (_scf_tmpl_add_error(errs
, SCF_TERR_WRONG_PROP_TYPE
, pg_name
,
5253 prop_name
, ev1
, NULL
, actual
, t_fmri
, t_pg_name
, t_pg_type
,
5254 t_prop_name
, t_prop_type
));
5269 * return 0 on success, -1 on failure.
5270 * set scf_error() to:
5271 * SCF_ERROR_BACKEND_ACCESS
5272 * SCF_ERROR_CONNECTION_BROKEN
5274 * SCF_ERROR_HANDLE_DESTROYED
5275 * SCF_ERROR_INTERNAL
5276 * SCF_ERROR_NO_MEMORY
5277 * SCF_ERROR_NO_RESOURCES
5278 * SCF_ERROR_NOT_BOUND
5279 * SCF_ERROR_PERMISSION_DENIED
5280 * SCF_ERROR_TEMPLATE_INVALID
5283 _add_tmpl_count_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
5284 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
,
5285 uint64_t count
, uint64_t *min
, uint64_t *max
)
5287 char *pg_name
= NULL
;
5288 char *prop_name
= NULL
;
5292 char *t_fmri
= NULL
;
5293 char *t_pg_name
= NULL
;
5294 char *t_pg_type
= NULL
;
5295 char *t_prop_name
= NULL
;
5296 char *t_prop_type
= NULL
;
5298 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5301 case SCF_TERR_RANGE_VIOLATION
:
5302 case SCF_TERR_CARDINALITY_VIOLATION
:
5303 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5305 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5308 case SCF_TERR_VALUE_OUT_OF_RANGE
:
5309 /* keep pg_name = NULL and prop_name = NULL */
5312 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5315 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5318 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5321 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5322 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5325 } else if (t_prop_type
== NULL
) {
5328 if (t_prop_type
== NULL
)
5329 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5330 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5334 if ((s_min
= strdup("")) == NULL
) {
5335 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5339 if ((s_min
= _val_to_string(*min
, 0)) == NULL
) {
5340 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5345 if ((s_max
= strdup("")) == NULL
) {
5346 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5350 if ((s_max
= _val_to_string(*max
, 0)) == NULL
) {
5351 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5355 if ((num
= _val_to_string(count
, 0)) == NULL
) {
5356 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5360 return (_scf_tmpl_add_error(errs
, type
, pg_name
, prop_name
, s_min
,
5361 s_max
, num
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
,
5378 * return 0 on success, -1 on failure.
5379 * set scf_error() to:
5380 * SCF_ERROR_BACKEND_ACCESS
5381 * SCF_ERROR_CONNECTION_BROKEN
5383 * SCF_ERROR_HANDLE_DESTROYED
5384 * SCF_ERROR_INTERNAL
5385 * SCF_ERROR_NO_MEMORY
5386 * SCF_ERROR_NO_RESOURCES
5387 * SCF_ERROR_NOT_BOUND
5388 * SCF_ERROR_PERMISSION_DENIED
5389 * SCF_ERROR_TEMPLATE_INVALID
5392 _add_tmpl_constraint_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
5393 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
,
5396 scf_type_t val_type
;
5397 char *pg_name
= NULL
;
5398 char *prop_name
= NULL
;
5400 char *t_fmri
= NULL
;
5401 char *t_pg_name
= NULL
;
5402 char *t_pg_type
= NULL
;
5403 char *t_prop_name
= NULL
;
5404 char *t_prop_type
= NULL
;
5406 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5409 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
5410 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5412 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5415 case SCF_TERR_INVALID_VALUE
:
5416 /* keep pg_name = NULL and prop_name = NULL */
5417 if ((value
= _scf_value_get_as_string(val
)) == NULL
)
5420 case SCF_TERR_PROP_TYPE_MISMATCH
:
5421 /* keep pg_name = NULL and prop_name = NULL */
5422 /* use value for value type */
5423 val_type
= scf_value_type(val
);
5424 if ((value
= strdup(scf_type_to_string(val_type
))) ==
5426 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5431 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5434 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5437 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5440 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5441 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5444 } else if (t_prop_type
== NULL
) {
5447 if (t_prop_type
== NULL
)
5448 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5449 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5453 return (_scf_tmpl_add_error(errs
, type
, pg_name
, prop_name
, NULL
, NULL
,
5454 value
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
, t_prop_type
));
5456 assert(scf_error() != SCF_ERROR_NOT_SET
);
5469 * return 0 on success, -1 on failure.
5470 * set scf_error() to:
5471 * SCF_ERROR_BACKEND_ACCESS
5472 * SCF_ERROR_CONNECTION_BROKEN
5474 * SCF_ERROR_HANDLE_DESTROYED
5475 * SCF_ERROR_INTERNAL
5476 * SCF_ERROR_NO_MEMORY
5477 * SCF_ERROR_NO_RESOURCES
5478 * SCF_ERROR_NOT_BOUND
5479 * SCF_ERROR_PERMISSION_DENIED
5480 * SCF_ERROR_TEMPLATE_INVALID
5483 _add_tmpl_int_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
5484 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
,
5485 int64_t val
, int64_t *min
, int64_t *max
)
5487 char *pg_name
= NULL
;
5488 char *prop_name
= NULL
;
5492 char *t_fmri
= NULL
;
5493 char *t_pg_name
= NULL
;
5494 char *t_pg_type
= NULL
;
5495 char *t_prop_name
= NULL
;
5496 char *t_prop_type
= NULL
;
5498 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5502 case SCF_TERR_RANGE_VIOLATION
:
5503 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5505 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5508 case SCF_TERR_VALUE_OUT_OF_RANGE
:
5509 /* keep pg_name = NULL and prop_name = NULL */
5512 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5515 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5518 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5521 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5522 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5525 } else if (t_prop_type
== NULL
) {
5528 if (t_prop_type
== NULL
)
5529 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5530 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5534 if ((s_min
= strdup("")) == NULL
) {
5535 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5539 if ((s_min
= _val_to_string(*((uint64_t *)min
), 1)) == NULL
) {
5540 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5545 if ((s_max
= strdup("")) == NULL
) {
5546 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5550 if ((s_max
= _val_to_string(*((uint64_t *)max
), 1)) == NULL
) {
5551 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5555 if ((value
= _val_to_string((uint64_t)val
, 1)) == NULL
) {
5556 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5560 return (_scf_tmpl_add_error(errs
, type
, pg_name
, prop_name
, s_min
,
5561 s_max
, value
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
,
5578 * return 0 on success, -1 on failure.
5579 * set scf_error() to:
5580 * SCF_ERROR_BACKEND_ACCESS
5581 * SCF_ERROR_CONNECTION_BROKEN
5583 * SCF_ERROR_HANDLE_DESTROYED
5584 * SCF_ERROR_INTERNAL
5585 * SCF_ERROR_NO_MEMORY
5586 * SCF_ERROR_NO_RESOURCES
5587 * SCF_ERROR_NOT_BOUND
5588 * SCF_ERROR_PERMISSION_DENIED
5589 * SCF_ERROR_TEMPLATE_INVALID
5592 _add_tmpl_pg_redefine_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
,
5597 char *t_fmri
= NULL
;
5598 char *t_pg_name
= NULL
;
5599 char *t_pg_type
= NULL
;
5601 if ((t_fmri
= _scf_tmpl_get_fmri(r
)) == NULL
)
5603 if (scf_tmpl_pg_name(r
, &t_pg_name
) == -1) {
5606 if (scf_tmpl_pg_type(r
, &t_pg_type
) == -1) {
5609 if (scf_tmpl_pg_name(t
, &ev1
) == -1) {
5612 if (scf_tmpl_pg_type(t
, &ev2
) == -1) {
5616 return (_scf_tmpl_add_error(errs
, SCF_TERR_PG_REDEFINE
, NULL
, NULL
,
5617 ev1
, ev2
, NULL
, t_fmri
, t_pg_name
, t_pg_type
, NULL
, NULL
));
5628 * return 0 if value is within count ranges constraint.
5629 * return -1 otherwise
5632 _check_count_ranges(scf_count_ranges_t
*cr
, uint64_t v
)
5636 for (i
= 0; i
< cr
->scr_num_ranges
; ++i
) {
5637 if (v
>= cr
->scr_min
[i
] &&
5638 v
<= cr
->scr_max
[i
]) {
5639 /* value is within ranges constraint */
5647 * return 0 if value is within count ranges constraint.
5648 * return -1 otherwise
5651 _check_int_ranges(scf_int_ranges_t
*ir
, int64_t v
)
5655 for (i
= 0; i
< ir
->sir_num_ranges
; ++i
) {
5656 if (v
>= ir
->sir_min
[i
] &&
5657 v
<= ir
->sir_max
[i
]) {
5658 /* value is within integer ranges constraint */
5666 * int _value_in_constraint()
5668 * Checks whether the supplied value violates any of the constraints
5669 * specified in the supplied property template. If it does, an appropriate
5670 * error is appended to "errs". pg and prop, if supplied, are used to
5671 * augment the information in the error. Returns 0 on success.
5673 * Returns -1 on failure. Sets scf_error():
5674 * SCF_ERROR_BACKEND_ACCESS
5675 * SCF_ERROR_CONNECTION_BROKEN
5677 * SCF_ERROR_HANDLE_DESTROYED
5678 * SCF_ERROR_INTERNAL
5679 * SCF_ERROR_INVALID_ARGUMENT
5680 * SCF_ERROR_NO_MEMORY
5681 * SCF_ERROR_NO_RESOURCES
5682 * SCF_ERROR_NOT_BOUND
5683 * SCF_ERROR_PERMISSION_DENIED
5684 * SCF_ERROR_TEMPLATE_INVALID
5687 _value_in_constraint(scf_propertygroup_t
*pg
, scf_property_t
*prop
,
5688 const scf_prop_tmpl_t
*pt
, scf_value_t
*value
, scf_tmpl_errors_t
*errs
)
5690 scf_type_t type
, tmpl_type
;
5692 scf_tmpl_error_type_t terr_type
;
5696 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
5702 scf_count_ranges_t cr
;
5703 scf_int_ranges_t ir
;
5705 type
= scf_value_type(value
);
5706 if (type
== SCF_TYPE_INVALID
) {
5707 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
5711 /* Check if template type matches value type. */
5712 if (scf_tmpl_prop_type(pt
, &tmpl_type
) == -1) {
5713 if (scf_error() != SCF_ERROR_NOT_FOUND
)
5714 /* type is not wildcarded */
5716 } else if (tmpl_type
!= type
) {
5718 if (pg
== NULL
&& prop
== NULL
) {
5719 if (_add_tmpl_constraint_error(errs
,
5720 SCF_TERR_PROP_TYPE_MISMATCH
, NULL
, pt
,
5728 /* Numeric values should be checked against any range constraints. */
5730 case SCF_TYPE_COUNT
:
5731 r
= scf_value_get_count(value
, &v_count
);
5734 if (scf_tmpl_value_count_range_constraints(pt
, &cr
) != 0) {
5735 if (scf_error() == SCF_ERROR_NOT_FOUND
)
5737 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
)
5738 (void) scf_set_error(
5739 SCF_ERROR_TEMPLATE_INVALID
);
5742 if (_check_count_ranges(&cr
, v_count
) == 0) {
5743 /* value is within ranges constraint */
5744 scf_count_ranges_destroy(&cr
);
5747 scf_count_ranges_destroy(&cr
);
5751 * If we get here, we have a possible constraint
5754 err_flag
|= 0x1; /* RANGE_VIOLATION, count */
5756 case SCF_TYPE_INTEGER
:
5757 if (scf_value_get_integer(value
, &v_int
) != 0)
5759 if (scf_tmpl_value_int_range_constraints(pt
, &ir
) != 0) {
5760 if (scf_error() == SCF_ERROR_NOT_FOUND
)
5762 if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED
)
5763 (void) scf_set_error(
5764 SCF_ERROR_TEMPLATE_INVALID
);
5767 if (_check_int_ranges(&ir
, v_int
) == 0) {
5768 /* value is within ranges constraint */
5769 scf_int_ranges_destroy(&ir
);
5772 scf_int_ranges_destroy(&ir
);
5775 * If we get here, we have a possible constraint
5778 err_flag
|= 0x2; /* RANGE_VIOLATION, integer */
5786 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5791 * If a set of names is provided, confirm value has one of
5794 if (scf_tmpl_value_name_constraints(pt
, &vals
) != 0) {
5796 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
5800 r
= scf_value_get_as_string_typed(value
, type
, vstr
, sz
);
5803 * All errors (INVALID_ARGUMENT, NOT_SET, TYPE_MISMATCH)
5804 * should be impossible or already caught above.
5808 constraints
= vals
.values
.v_astring
;
5809 for (n
= 0; constraints
[n
] != NULL
; ++n
) {
5810 if (strcmp(constraints
[n
], vstr
) == 0) {
5811 /* value is within constraint */
5812 scf_values_destroy(&vals
);
5817 /* if we get here, we have a constraint violation */
5818 err_flag
|= 0x4; /* CONSTRAINT_VIOLATED */
5819 scf_values_destroy(&vals
);
5824 /* register the errors found */
5825 if (ret
== 1 && errs
!= NULL
) {
5826 if ((err_flag
& 0x1) == 0x1) {
5828 * Help make the error more human-friendly. If
5829 * pg and prop are provided, we know we're
5830 * validating repository data. If they're not,
5831 * we're validating a potentially hypothetical
5834 if (pg
== NULL
&& prop
== NULL
)
5835 terr_type
= SCF_TERR_VALUE_OUT_OF_RANGE
;
5837 terr_type
= SCF_TERR_RANGE_VIOLATION
;
5838 if (_add_tmpl_count_error(errs
, terr_type
, pg
, pt
,
5839 prop
, v_count
, 0, 0) == -1)
5842 if ((err_flag
& 0x2) == 0x2) {
5843 if (pg
== NULL
&& prop
== NULL
)
5844 terr_type
= SCF_TERR_VALUE_OUT_OF_RANGE
;
5846 terr_type
= SCF_TERR_RANGE_VIOLATION
;
5847 if (_add_tmpl_int_error(errs
, terr_type
, pg
, pt
, prop
,
5851 if ((err_flag
& 0x4) == 0x4) {
5852 if (pg
== NULL
&& prop
== NULL
)
5853 terr_type
= SCF_TERR_INVALID_VALUE
;
5855 terr_type
= SCF_TERR_VALUE_CONSTRAINT_VIOLATED
;
5856 if (_add_tmpl_constraint_error(errs
, terr_type
, pg
,
5857 pt
, prop
, value
) == -1)
5865 * Returns -1 on failure. Sets scf_error():
5866 * SCF_ERROR_BACKEND_ACCESS
5867 * SCF_ERROR_CONNECTION_BROKEN
5869 * SCF_ERROR_HANDLE_DESTROYED
5870 * SCF_ERROR_INTERNAL
5871 * SCF_ERROR_INVALID_ARGUMENT
5872 * SCF_ERROR_NO_MEMORY
5873 * SCF_ERROR_NO_RESOURCES
5874 * SCF_ERROR_NOT_BOUND
5875 * SCF_ERROR_PERMISSION_DENIED
5876 * SCF_ERROR_TEMPLATE_INVALID
5879 scf_tmpl_value_in_constraint(const scf_prop_tmpl_t
*pt
, scf_value_t
*value
,
5880 scf_tmpl_errors_t
**errs
)
5882 scf_tmpl_errors_t
*e
= NULL
;
5887 if ((fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5889 *errs
= _scf_create_errors(fmri
, 1);
5896 return (_value_in_constraint(NULL
, NULL
, pt
, value
, e
));
5900 scf_tmpl_next_error(scf_tmpl_errors_t
*errs
)
5902 if (errs
->tes_index
< errs
->tes_num_errs
) {
5903 assert(errs
->tes_errs
[errs
->tes_index
] != NULL
);
5904 return (errs
->tes_errs
[errs
->tes_index
++]);
5911 scf_tmpl_reset_errors(scf_tmpl_errors_t
*errs
)
5913 errs
->tes_index
= 0;
5917 scf_tmpl_strerror(scf_tmpl_error_t
*err
, char *s
, size_t n
, int flag
)
5922 int nsz
= 0; /* err msg length */
5923 int sz
= n
; /* available buffer size */
5924 char *buf
= s
; /* where to append in buffer */
5925 char *s0
= (flag
== SCF_TMPL_STRERROR_HUMAN
) ? ":\n\t" : ": ";
5926 char *s1
= (flag
== SCF_TMPL_STRERROR_HUMAN
) ? "\n\t" : "; ";
5931 if (err
->te_errs
->tes_prefix
!= NULL
) {
5932 ret
= snprintf(buf
, sz
, "%s", dgettext(TEXT_DOMAIN
,
5933 err
->te_errs
->tes_prefix
));
5935 sz
= (sz
- ret
) > 0 ? sz
- ret
: 0;
5936 buf
= (sz
> 0) ? s
+ nsz
: NULL
;
5939 ret
= snprintf(buf
, sz
, "%s", dgettext(TEXT_DOMAIN
,
5940 em_desc
[err
->te_type
].em_msg
));
5942 sz
= (sz
- ret
) > 0 ? sz
- ret
: 0;
5943 buf
= (sz
> 0) ? s
+ nsz
: NULL
;
5945 for (i
= 0; _tmpl_error_items
[i
].get_desc
!= NULL
; ++i
) {
5946 if ((str
= _tmpl_error_items
[i
].get_desc(err
)) == NULL
)
5947 /* no item to print */
5949 val
= _tmpl_error_items
[i
].get_val(err
);
5950 ret
= snprintf(buf
, sz
, "%s%s=\"%s\"", sep
, str
,
5951 (val
== NULL
) ? "" : val
);
5953 sz
= (sz
- ret
) > 0 ? sz
- ret
: 0;
5954 buf
= (sz
> 0) ? s
+ nsz
: NULL
;
5961 * return 0 on success, -1 on failure.
5962 * set scf_error() to:
5963 * SCF_ERROR_BACKEND_ACCESS
5964 * SCF_ERROR_CONNECTION_BROKEN
5966 * SCF_ERROR_HANDLE_DESTROYED
5967 * SCF_ERROR_INTERNAL
5968 * SCF_ERROR_NO_MEMORY
5969 * SCF_ERROR_NO_RESOURCES
5970 * SCF_ERROR_NOT_BOUND
5971 * SCF_ERROR_PERMISSION_DENIED
5972 * SCF_ERROR_TEMPLATE_INVALID
5975 _validate_cardinality(scf_propertygroup_t
*pg
, scf_prop_tmpl_t
*pt
,
5976 scf_property_t
*prop
, scf_tmpl_errors_t
*errs
)
5980 scf_iter_t
*iter
= NULL
;
5981 scf_value_t
*val
= NULL
;
5986 if (scf_tmpl_prop_cardinality(pt
, &min
, &max
) != 0) {
5987 if (scf_error() == SCF_ERROR_NOT_FOUND
)
5993 /* Any number of values permitted. Just return success. */
5994 if (min
== 0 && max
== UINT64_MAX
) {
5998 h
= scf_property_handle(prop
);
6000 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
6004 iter
= scf_iter_create(h
);
6005 val
= scf_value_create(h
);
6006 if (iter
== NULL
|| val
== NULL
) {
6007 if (ismember(scf_error(), errors_server
)) {
6015 if (scf_iter_property_values(iter
, prop
) != 0) {
6016 if (ismember(scf_error(), errors_server
)) {
6024 while ((r
= scf_iter_next_value(iter
, val
)) == 1)
6028 if (ismember(scf_error(), errors_server
)) {
6036 if (count
< min
|| count
> max
)
6037 if (_add_tmpl_count_error(errs
, SCF_TERR_CARDINALITY_VIOLATION
,
6038 pg
, pt
, prop
, (uint64_t)count
, &min
, &max
) == -1)
6044 scf_iter_destroy(iter
);
6045 scf_value_destroy(val
);
6050 * Returns -1 on error. Sets scf_error():
6051 * SCF_ERROR_BACKEND_ACCESS
6052 * SCF_ERROR_CONNECTION_BROKEN
6054 * SCF_ERROR_HANDLE_DESTROYED
6055 * SCF_ERROR_INTERNAL
6056 * SCF_ERROR_NO_MEMORY
6057 * SCF_ERROR_NO_RESOURCES
6058 * SCF_ERROR_NOT_BOUND
6059 * SCF_ERROR_PERMISSION_DENIED
6060 * SCF_ERROR_TEMPLATE_INVALID
6063 _check_property(scf_prop_tmpl_t
*pt
, scf_propertygroup_t
*pg
,
6064 scf_property_t
*prop
, scf_tmpl_errors_t
*errs
)
6066 scf_type_t tmpl_type
;
6069 scf_iter_t
*iter
= NULL
;
6070 scf_value_t
*val
= NULL
;
6074 h
= scf_pg_handle(pg
);
6076 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
6080 iter
= scf_iter_create(h
);
6081 val
= scf_value_create(h
);
6082 if (iter
== NULL
|| val
== NULL
) {
6083 if (ismember(scf_error(), errors_server
)) {
6084 scf_iter_destroy(iter
);
6085 scf_value_destroy(val
);
6093 if (scf_tmpl_prop_required(pt
, &required
) != 0)
6097 if (scf_tmpl_prop_type(pt
, &tmpl_type
) == -1) {
6098 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
6100 } else if (required
) {
6101 /* If required, type must be specified. */
6102 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6105 } else if (scf_property_is_type(prop
, tmpl_type
) != 0) {
6106 if (ismember(scf_error(), errors_server
)) {
6108 } else switch (scf_error()) {
6109 case SCF_ERROR_TYPE_MISMATCH
:
6110 if (_add_tmpl_wrong_prop_type_error(errs
, pg
, pt
,
6115 case SCF_ERROR_INVALID_ARGUMENT
:
6117 * tmpl_prop_type shouldn't have handed back
6118 * an invalid property type.
6120 case SCF_ERROR_NOT_SET
:
6129 if (_validate_cardinality(pg
, pt
, prop
, errs
) == -1)
6132 /* Value constraints */
6134 * Iterate through each value, and confirm it is defined as
6137 if (scf_iter_property_values(iter
, prop
) != 0) {
6138 assert(scf_error() != SCF_ERROR_NOT_SET
&&
6139 scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
6143 while ((r
= scf_iter_next_value(iter
, val
)) == 1) {
6144 if (_value_in_constraint(pg
, prop
, pt
, val
, errs
) == -1) {
6145 if (ismember(scf_error(), errors_server
)) {
6147 } else switch (scf_error()) {
6148 case SCF_ERROR_TEMPLATE_INVALID
:
6151 case SCF_ERROR_INVALID_ARGUMENT
:
6160 if (ismember(scf_error(), errors_server
)) {
6171 scf_iter_destroy(iter
);
6172 scf_value_destroy(val
);
6177 * Returns -1 on failure, sets scf_error() to:
6178 * SCF_ERROR_BACKEND_ACCESS
6179 * SCF_ERROR_CONNECTION_BROKEN
6181 * SCF_ERROR_HANDLE_DESTROYED
6182 * SCF_ERROR_INTERNAL
6183 * SCF_ERROR_NO_MEMORY
6184 * SCF_ERROR_NO_RESOURCES
6185 * SCF_ERROR_NOT_BOUND
6186 * SCF_ERROR_PERMISSION_DENIED
6187 * SCF_ERROR_TEMPLATE_INVALID
6190 _check_pg(scf_pg_tmpl_t
*t
, scf_propertygroup_t
*pg
, char *pg_name
,
6191 char *type
, scf_tmpl_errors_t
*errs
)
6193 scf_prop_tmpl_t
*pt
= NULL
;
6194 char *pg_type
= NULL
;
6195 scf_iter_t
*iter
= NULL
;
6196 uint8_t pg_required
;
6197 scf_property_t
*prop
= NULL
;
6200 char *prop_name
= NULL
;
6201 ssize_t nsize
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
6204 assert(pg_name
!= NULL
);
6207 assert(type
!= NULL
);
6210 if ((h
= scf_pg_handle(pg
)) == NULL
) {
6211 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
6214 if ((pt
= scf_tmpl_prop_create(h
)) == NULL
) {
6215 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
6219 if ((prop
= scf_property_create(h
)) == NULL
) {
6220 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
6224 if ((iter
= scf_iter_create(h
)) == NULL
) {
6225 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
6228 if ((prop_name
= malloc(nsize
)) == NULL
) {
6229 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
6233 if (scf_tmpl_pg_required(t
, &pg_required
) != 0)
6236 if (scf_tmpl_pg_type(t
, &pg_type
) == -1) {
6238 } else if (pg_required
!= 0 &&
6239 strcmp(SCF_TMPL_WILDCARD
, pg_type
) == 0) {
6240 /* Type must be specified for required pgs. */
6241 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6245 if (pg_type
!= NULL
) {
6246 if (strcmp(pg_type
, type
) != 0 &&
6247 strcmp(pg_type
, SCF_TMPL_WILDCARD
) != 0) {
6248 if (_add_tmpl_wrong_pg_type_error(errs
, t
, pg
) == -1)
6254 /* Iterate through properties in the repository and check them. */
6255 if (scf_iter_pg_properties(iter
, pg
) != 0) {
6256 if (ismember(scf_error(), errors_server
)) {
6264 while ((r
= scf_iter_next_property(iter
, prop
)) == 1) {
6265 if (scf_property_get_name(prop
, prop_name
, nsize
) == -1) {
6266 assert(scf_error() != SCF_ERROR_NOT_SET
);
6269 if (scf_tmpl_get_by_prop(t
, prop_name
, pt
, 0) != 0) {
6270 if (ismember(scf_error(), errors_server
)) {
6272 } else switch (scf_error()) {
6273 case SCF_ERROR_NOT_FOUND
:
6274 /* No template. Continue. */
6277 case SCF_ERROR_INVALID_ARGUMENT
:
6284 if (_check_property(pt
, pg
, prop
, errs
) != 0)
6289 if (ismember(scf_error(), errors_server
)) {
6297 scf_tmpl_prop_reset(pt
);
6301 * Confirm required properties are present.
6303 while ((r
= scf_tmpl_iter_props(t
, pt
,
6304 SCF_PROP_TMPL_FLAG_REQUIRED
)) == 0) {
6305 scf_type_t prop_type
;
6307 if (scf_tmpl_prop_name(pt
, &prop_name
) == -1)
6310 /* required properties cannot have type wildcarded */
6311 if (scf_tmpl_prop_type(pt
, &prop_type
) == -1) {
6312 if (scf_error() == SCF_ERROR_NOT_FOUND
)
6313 (void) scf_set_error(
6314 SCF_ERROR_TEMPLATE_INVALID
);
6318 if (scf_pg_get_property(pg
, prop_name
, prop
) != 0) {
6319 if (ismember(scf_error(), errors_server
)) {
6321 } else switch (scf_error()) {
6322 case SCF_ERROR_NOT_FOUND
:
6323 if (_add_tmpl_missing_prop_error(errs
, t
, pg
,
6328 case SCF_ERROR_INVALID_ARGUMENT
:
6329 (void) scf_set_error(
6330 SCF_ERROR_TEMPLATE_INVALID
);
6333 case SCF_ERROR_HANDLE_MISMATCH
:
6334 case SCF_ERROR_NOT_SET
:
6344 if (ismember(scf_error(), errors_server
)) {
6346 } else switch (scf_error()) {
6347 case SCF_ERROR_NOT_FOUND
:
6350 case SCF_ERROR_TEMPLATE_INVALID
:
6353 case SCF_ERROR_INVALID_ARGUMENT
:
6362 scf_tmpl_prop_destroy(pt
);
6363 scf_iter_destroy(iter
);
6364 scf_property_destroy(prop
);
6371 * Checks if instance fmri redefines any pgs defined in restarter or global
6372 * Return -1 on failure, sets scf_error() to:
6373 * SCF_ERROR_BACKEND_ACCESS
6374 * SCF_ERROR_CONNECTION_BROKEN
6376 * SCF_ERROR_HANDLE_DESTROYED
6377 * SCF_ERROR_INTERNAL
6378 * SCF_ERROR_INVALID_ARGUMENT
6379 * SCF_ERROR_NO_MEMORY
6380 * SCF_ERROR_NO_RESOURCES
6381 * SCF_ERROR_NOT_BOUND
6382 * SCF_ERROR_NOT_FOUND
6383 * SCF_ERROR_PERMISSION_DENIED
6384 * SCF_ERROR_TEMPLATE_INVALID
6387 _scf_tmpl_check_pg_redef(scf_handle_t
*h
, const char *fmri
,
6388 const char *snapname
, scf_tmpl_errors_t
*errs
)
6390 scf_pg_tmpl_t
*t
= NULL
;
6391 scf_pg_tmpl_t
*r
= NULL
;
6392 char *pg_name
= NULL
;
6393 char *pg_name_r
= NULL
;
6394 char *pg_type
= NULL
;
6395 char *pg_type_r
= NULL
;
6396 char *target
= NULL
;
6400 t
= scf_tmpl_pg_create(h
);
6401 r
= scf_tmpl_pg_create(h
);
6402 if (t
== NULL
|| r
== NULL
)
6405 while ((ret
= scf_tmpl_iter_pgs(t
, fmri
, snapname
, NULL
,
6406 SCF_PG_TMPL_FLAG_EXACT
)) == 1) {
6407 if (scf_tmpl_pg_name(t
, &pg_name
) == -1) {
6410 if (scf_tmpl_pg_type(t
, &pg_type
) == -1) {
6413 /* look for a redefinition of a global/restarter pg_pattern */
6414 while ((ret
= scf_tmpl_iter_pgs(r
, fmri
, snapname
, pg_type
,
6416 if (scf_tmpl_pg_name(r
, &pg_name_r
) == -1) {
6418 } else if (strcmp(pg_name_r
, SCF_TMPL_WILDCARD
) != 0 &&
6419 strcmp(pg_name
, SCF_TMPL_WILDCARD
) != 0 &&
6420 strcmp(pg_name
, pg_name_r
) != 0) {
6426 if (scf_tmpl_pg_type(r
, &pg_type_r
) == -1) {
6428 } else if (strcmp(pg_type_r
, SCF_TMPL_WILDCARD
) != 0 &&
6429 strcmp(pg_type
, SCF_TMPL_WILDCARD
) != 0 &&
6430 strcmp(pg_type
, pg_type_r
) != 0) {
6438 if (scf_tmpl_pg_target(r
, &target
) == -1) {
6442 if (strcmp(target
, SCF_TM_TARGET_ALL
) == 0 ||
6443 strcmp(target
, SCF_TM_TARGET_DELEGATE
) == 0) {
6444 /* found a pg_pattern redefinition */
6445 if (_add_tmpl_pg_redefine_error(errs
, t
,
6465 scf_tmpl_pg_reset(r
);
6478 scf_tmpl_pg_destroy(t
);
6479 scf_tmpl_pg_destroy(r
);
6486 if (ret_val
== -1) {
6487 if (!ismember(scf_error(), errors_server
)) {
6488 switch (scf_error()) {
6489 case SCF_ERROR_TYPE_MISMATCH
:
6490 (void) scf_set_error(
6491 SCF_ERROR_TEMPLATE_INVALID
);
6494 case SCF_ERROR_CONSTRAINT_VIOLATED
:
6495 case SCF_ERROR_INVALID_ARGUMENT
:
6496 case SCF_ERROR_NOT_FOUND
:
6497 case SCF_ERROR_TEMPLATE_INVALID
:
6500 case SCF_ERROR_HANDLE_MISMATCH
:
6501 case SCF_ERROR_NOT_SET
:
6512 * Returns -1 on failure, sets scf_error() to:
6513 * SCF_ERROR_BACKEND_ACCESS
6514 * SCF_ERROR_CONNECTION_BROKEN
6516 * SCF_ERROR_HANDLE_DESTROYED
6517 * SCF_ERROR_INTERNAL
6518 * SCF_ERROR_INVALID_ARGUMENT
6519 * SCF_ERROR_NO_MEMORY
6520 * SCF_ERROR_NO_RESOURCES
6521 * SCF_ERROR_NOT_BOUND
6522 * SCF_ERROR_NOT_FOUND
6523 * SCF_ERROR_PERMISSION_DENIED
6524 * SCF_ERROR_TEMPLATE_INVALID
6527 scf_tmpl_validate_fmri(scf_handle_t
*h
, const char *fmri
, const char *snapshot
,
6528 scf_tmpl_errors_t
**errs
, int flags
)
6530 scf_pg_tmpl_t
*t
= NULL
;
6531 scf_iter_t
*iter
= NULL
;
6532 scf_propertygroup_t
*pg
= NULL
;
6533 scf_instance_t
*inst
= NULL
;
6534 scf_snapshot_t
*snap
= NULL
;
6536 char *pg_name
= NULL
;
6537 ssize_t rsize
= scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH
) + 1;
6538 ssize_t nsize
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
6542 assert(errs
!= NULL
);
6544 if ((*errs
= _scf_create_errors(fmri
, 1)) == NULL
)
6547 if ((pg
= scf_pg_create(h
)) == NULL
||
6548 (iter
= scf_iter_create(h
)) == NULL
||
6549 (inst
= scf_instance_create(h
)) == NULL
||
6550 (t
= scf_tmpl_pg_create(h
)) == NULL
) {
6552 * Sets SCF_ERROR_INVALID_ARGUMENT, SCF_ERROR_NO_MEMORY,
6553 * SCF_ERROR_NO_RESOURCES, SCF_ERROR_INTERNAL or
6554 * SCF_ERROR_HANDLE_DESTROYED.
6559 if ((type
= malloc(rsize
)) == NULL
||
6560 (pg_name
= malloc(nsize
)) == NULL
) {
6561 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
6565 if (scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, inst
, NULL
, NULL
,
6566 SCF_DECODE_FMRI_EXACT
|SCF_DECODE_FMRI_REQUIRE_INSTANCE
) != 0) {
6567 if (ismember(scf_error(), errors_server
)) {
6569 } else switch (scf_error()) {
6570 case SCF_ERROR_CONSTRAINT_VIOLATED
:
6571 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6574 case SCF_ERROR_INVALID_ARGUMENT
:
6575 case SCF_ERROR_NOT_FOUND
:
6578 case SCF_ERROR_HANDLE_MISMATCH
:
6579 case SCF_ERROR_NOT_SET
:
6586 if (snapshot
== NULL
|| strcmp(snapshot
, "running") == 0 ||
6587 (flags
& SCF_TMPL_VALIDATE_FLAG_CURRENT
)) {
6588 if (_get_snapshot(inst
, NULL
, &snap
) == -1)
6591 (void) scf_set_error(SCF_ERROR_NONE
);
6592 if (_get_snapshot(inst
, snapshot
, &snap
) == -1) {
6594 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
6598 if (_scf_tmpl_check_pg_redef(h
, fmri
, snapshot
, *errs
) != 0) {
6603 * Check that property groups on this instance conform to the template.
6605 if (scf_iter_instance_pgs_composed(iter
, inst
, snap
) != 0) {
6606 if (ismember(scf_error(), errors_server
)) {
6614 while ((r
= scf_iter_next_pg(iter
, pg
)) == 1) {
6615 if (scf_pg_get_name(pg
, pg_name
, nsize
) == -1) {
6616 if (ismember(scf_error(), errors_server
)) {
6624 if (scf_pg_get_type(pg
, type
, rsize
) == -1) {
6625 if (ismember(scf_error(), errors_server
)) {
6633 if (scf_tmpl_get_by_pg_name(fmri
, snapshot
, pg_name
, type
, t
,
6635 if (ismember(scf_error(), errors_server
)) {
6637 } else switch (scf_error()) {
6638 case SCF_ERROR_NOT_FOUND
:
6641 case SCF_ERROR_INVALID_ARGUMENT
:
6650 if (_check_pg(t
, pg
, pg_name
, type
, *errs
) != 0)
6654 if (ismember(scf_error(), errors_server
)) {
6662 scf_tmpl_pg_reset(t
);
6665 * Confirm required property groups are present.
6667 while ((r
= scf_tmpl_iter_pgs(t
, fmri
, snapshot
, NULL
,
6668 SCF_PG_TMPL_FLAG_REQUIRED
)) == 1) {
6672 if (scf_tmpl_pg_name(t
, &pg_name
) == -1)
6674 if (scf_tmpl_pg_type(t
, &type
) == -1)
6677 * required property group templates should not have
6678 * wildcarded name or type
6680 if (strcmp(pg_name
, SCF_TMPL_WILDCARD
) == 0 ||
6681 strcmp(type
, SCF_TMPL_WILDCARD
) == 0) {
6682 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6686 if (_get_pg(NULL
, inst
, snap
, pg_name
, pg
) != 0) {
6687 if (ismember(scf_error(), errors_server
)) {
6689 } else switch (scf_error()) {
6690 case SCF_ERROR_NOT_FOUND
:
6691 if (_add_tmpl_missing_pg_error(*errs
, t
) == -1)
6695 case SCF_ERROR_INVALID_ARGUMENT
:
6696 case SCF_ERROR_HANDLE_MISMATCH
:
6697 case SCF_ERROR_NOT_SET
:
6705 if (ismember(scf_error(), errors_server
)) {
6707 } else switch (scf_error()) {
6708 case SCF_ERROR_NOT_FOUND
:
6711 case SCF_ERROR_INVALID_ARGUMENT
:
6721 if ((*errs
)->tes_num_errs
> 0)
6725 /* there are no errors to report */
6726 scf_tmpl_errors_destroy(*errs
);
6729 scf_tmpl_pg_destroy(t
);
6733 scf_iter_destroy(iter
);
6735 scf_instance_destroy(inst
);
6736 scf_snapshot_destroy(snap
);
6742 scf_tmpl_errors_destroy(scf_tmpl_errors_t
*errs
)
6745 scf_tmpl_error_t
*e
;
6750 for (i
= 0; i
< errs
->tes_num_errs
; ++i
) {
6751 e
= errs
->tes_errs
[i
];
6752 if (errs
->tes_flag
!= 0) {
6753 free((char *)e
->te_pg_name
);
6754 free((char *)e
->te_prop_name
);
6755 free((char *)e
->te_ev1
);
6756 free((char *)e
->te_ev2
);
6757 free((char *)e
->te_actual
);
6758 free((char *)e
->te_tmpl_fmri
);
6759 free((char *)e
->te_tmpl_pg_name
);
6760 free((char *)e
->te_tmpl_pg_type
);
6761 free((char *)e
->te_tmpl_prop_name
);
6762 free((char *)e
->te_tmpl_prop_type
);
6766 free((char *)errs
->tes_fmri
);
6767 free((char *)errs
->tes_prefix
);
6768 free(errs
->tes_errs
);
6773 scf_tmpl_error_source_fmri(const scf_tmpl_error_t
*err
, char **fmri
)
6775 assert(err
!= NULL
);
6776 switch (err
->te_type
) {
6777 case SCF_TERR_MISSING_PG
:
6778 case SCF_TERR_WRONG_PG_TYPE
:
6779 case SCF_TERR_MISSING_PROP
:
6780 case SCF_TERR_WRONG_PROP_TYPE
:
6781 case SCF_TERR_CARDINALITY_VIOLATION
:
6782 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6783 case SCF_TERR_RANGE_VIOLATION
:
6784 case SCF_TERR_PROP_TYPE_MISMATCH
:
6785 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6786 case SCF_TERR_INVALID_VALUE
:
6787 case SCF_TERR_PG_REDEFINE
:
6788 *fmri
= (char *)err
->te_tmpl_fmri
;
6792 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6798 scf_tmpl_error_type(const scf_tmpl_error_t
*err
, scf_tmpl_error_type_t
*type
)
6800 assert(err
!= NULL
);
6801 switch (err
->te_type
) {
6802 case SCF_TERR_MISSING_PG
:
6803 case SCF_TERR_WRONG_PG_TYPE
:
6804 case SCF_TERR_MISSING_PROP
:
6805 case SCF_TERR_WRONG_PROP_TYPE
:
6806 case SCF_TERR_CARDINALITY_VIOLATION
:
6807 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6808 case SCF_TERR_RANGE_VIOLATION
:
6809 case SCF_TERR_PROP_TYPE_MISMATCH
:
6810 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6811 case SCF_TERR_INVALID_VALUE
:
6812 case SCF_TERR_PG_REDEFINE
:
6813 *type
= err
->te_type
;
6817 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6823 scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6825 assert(err
!= NULL
);
6826 switch (err
->te_type
) {
6827 case SCF_TERR_MISSING_PG
:
6828 case SCF_TERR_WRONG_PG_TYPE
:
6829 case SCF_TERR_MISSING_PROP
:
6830 case SCF_TERR_WRONG_PROP_TYPE
:
6831 case SCF_TERR_CARDINALITY_VIOLATION
:
6832 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6833 case SCF_TERR_RANGE_VIOLATION
:
6834 case SCF_TERR_PROP_TYPE_MISMATCH
:
6835 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6836 case SCF_TERR_INVALID_VALUE
:
6837 case SCF_TERR_PG_REDEFINE
:
6838 if (err
->te_tmpl_pg_name
!= NULL
&&
6839 err
->te_tmpl_pg_type
!= NULL
) {
6841 *name
= (char *)err
->te_tmpl_pg_name
;
6843 *type
= (char *)err
->te_tmpl_pg_type
;
6846 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6849 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6855 scf_tmpl_error_pg(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6857 assert(err
!= NULL
);
6858 switch (err
->te_type
) {
6859 case SCF_TERR_WRONG_PG_TYPE
:
6860 if (err
->te_pg_name
!= NULL
&&
6861 err
->te_actual
!= NULL
) {
6863 *name
= (char *)err
->te_pg_name
;
6865 *type
= (char *)err
->te_actual
;
6868 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6870 case SCF_TERR_WRONG_PROP_TYPE
:
6871 case SCF_TERR_CARDINALITY_VIOLATION
:
6872 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6873 case SCF_TERR_RANGE_VIOLATION
:
6874 if (err
->te_pg_name
!= NULL
&&
6875 err
->te_tmpl_pg_type
!= NULL
) {
6877 *name
= (char *)err
->te_pg_name
;
6879 *type
= (char *)err
->te_tmpl_pg_type
;
6883 case SCF_TERR_MISSING_PROP
:
6884 case SCF_TERR_MISSING_PG
:
6885 case SCF_TERR_PROP_TYPE_MISMATCH
:
6886 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6887 case SCF_TERR_INVALID_VALUE
:
6888 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6890 case SCF_TERR_PG_REDEFINE
:
6891 if (err
->te_ev1
!= NULL
&& err
->te_ev2
!= NULL
) {
6893 *name
= (char *)err
->te_ev1
;
6895 *type
= (char *)err
->te_ev2
;
6898 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6901 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6907 scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6909 assert(err
!= NULL
);
6910 switch (err
->te_type
) {
6911 case SCF_TERR_MISSING_PROP
:
6912 case SCF_TERR_WRONG_PROP_TYPE
:
6913 case SCF_TERR_CARDINALITY_VIOLATION
:
6914 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6915 case SCF_TERR_RANGE_VIOLATION
:
6916 case SCF_TERR_PROP_TYPE_MISMATCH
:
6917 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6918 case SCF_TERR_INVALID_VALUE
:
6919 if (err
->te_tmpl_prop_name
!= NULL
&&
6920 err
->te_tmpl_prop_type
!= NULL
) {
6922 *name
= (char *)err
->te_tmpl_prop_name
;
6924 *type
= (char *)err
->te_tmpl_prop_type
;
6928 case SCF_TERR_MISSING_PG
:
6929 case SCF_TERR_WRONG_PG_TYPE
:
6930 case SCF_TERR_PG_REDEFINE
:
6931 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6934 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6940 scf_tmpl_error_prop(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6942 assert(err
!= NULL
);
6943 switch (err
->te_type
) {
6944 case SCF_TERR_WRONG_PROP_TYPE
:
6945 case SCF_TERR_CARDINALITY_VIOLATION
:
6946 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6947 case SCF_TERR_RANGE_VIOLATION
:
6948 if (err
->te_prop_name
!= NULL
&&
6949 err
->te_tmpl_prop_type
!= NULL
) {
6951 *name
= (char *)err
->te_prop_name
;
6953 *type
= (char *)err
->te_tmpl_prop_type
;
6957 case SCF_TERR_MISSING_PG
:
6958 case SCF_TERR_WRONG_PG_TYPE
:
6959 case SCF_TERR_MISSING_PROP
:
6960 case SCF_TERR_PROP_TYPE_MISMATCH
:
6961 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6962 case SCF_TERR_INVALID_VALUE
:
6963 case SCF_TERR_PG_REDEFINE
:
6964 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6967 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6973 scf_tmpl_error_value(const scf_tmpl_error_t
*err
, char **val
)
6975 assert(err
!= NULL
);
6976 switch (err
->te_type
) {
6977 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6978 case SCF_TERR_RANGE_VIOLATION
:
6979 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6980 case SCF_TERR_INVALID_VALUE
:
6981 if (err
->te_actual
!= NULL
) {
6983 *val
= (char *)err
->te_actual
;
6987 case SCF_TERR_MISSING_PG
:
6988 case SCF_TERR_WRONG_PG_TYPE
:
6989 case SCF_TERR_MISSING_PROP
:
6990 case SCF_TERR_WRONG_PROP_TYPE
:
6991 case SCF_TERR_CARDINALITY_VIOLATION
:
6992 case SCF_TERR_PROP_TYPE_MISMATCH
:
6993 case SCF_TERR_PG_REDEFINE
:
6994 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6997 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
7003 scf_tmpl_visibility_to_string(uint8_t vis
)
7005 if (vis
== SCF_TMPL_VISIBILITY_READONLY
)
7006 return (SCF_TM_VISIBILITY_READONLY
);
7007 else if (vis
== SCF_TMPL_VISIBILITY_HIDDEN
)
7008 return (SCF_TM_VISIBILITY_HIDDEN
);
7009 else if (vis
== SCF_TMPL_VISIBILITY_READWRITE
)
7010 return (SCF_TM_VISIBILITY_READWRITE
);