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 if (vals
->values
.v_astring
[i
] != NULL
)
650 free(vals
->values
.v_astring
[i
]);
651 vals
->values
.v_astring
[i
] = NULL
;
653 free(vals
->values
.v_astring
);
654 vals
->values
.v_astring
= NULL
;
655 vals
->value_count
= 0;
657 append_single_astring_from_pg_done
:
658 scf_iter_destroy(iter
);
659 scf_property_destroy(prop
);
660 scf_value_destroy(val
);
661 return (vals
->values
.v_astring
);
665 * Returns NULL on failure, sets scf_error() to:
666 * SCF_ERROR_BACKEND_ACCESS
667 * SCF_ERROR_CONNECTION_BROKEN
669 * SCF_ERROR_HANDLE_DESTROYED
671 * SCF_ERROR_INVALID_ARGUMENT
672 * prop_name is not a valid property name.
673 * SCF_ERROR_NO_MEMORY
674 * SCF_ERROR_NO_RESOURCES
675 * SCF_ERROR_NOT_BOUND
676 * SCF_ERROR_NOT_FOUND
678 * SCF_ERROR_PERMISSION_DENIED
679 * SCF_ERROR_TYPE_MISMATCH
682 _read_astrings_values(scf_propertygroup_t
*pg
, const char *prop_name
,
685 assert(vals
!= NULL
);
686 vals
->value_count
= 0;
687 vals
->value_type
= SCF_TYPE_ASTRING
;
688 vals
->reserved
= NULL
;
689 return (_append_astrings_values(pg
, prop_name
, vals
));
693 _scf_sanitize_locale(char *locale
)
695 for (; *locale
!= '\0'; locale
++)
696 if (!isalnum(*locale
) && *locale
!= '_')
701 * The returned string needs to be freed by the caller
702 * Returns NULL on failure. Sets scf_error() to:
703 * SCF_ERROR_NO_MEMORY
704 * SCF_ERROR_INVALID_ARGUMENT
705 * Name isn't short enough to add the locale to.
708 _add_locale_to_name(const char *name
, const char *locale
)
715 locale
= setlocale(LC_MESSAGES
, NULL
);
716 loc
= strdup(locale
);
718 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
721 _scf_sanitize_locale(loc
);
724 lsz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
727 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
731 (void) strlcpy(lname
, name
, lsz
);
732 if (strlcat(lname
, loc
, lsz
) >= lsz
) {
733 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
744 * char *_tmpl_pg_name(pg, type, use_type)
746 * pg and type can both be NULL. Returns the name of the most specific
747 * template property group name based on the inputs.
748 * If use_type is set and pg is not NULL, a property group name for a
749 * property group template that has type defined is returned, even if no
752 * Returns NULL on failure and sets scf_error() to:
753 * SCF_ERROR_INVALID_ARGUMENT
754 * can't combine the arguments and get a reasonable length name
755 * SCF_ERROR_NO_MEMORY
759 _tmpl_pg_name(const char *pg
, const char *type
, int use_type
)
762 ssize_t limit
, size
= 0;
764 limit
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
765 name
= malloc(limit
);
767 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
771 if (pg
== NULL
&& type
== NULL
) {
772 if (strlcpy(name
, SCF_PG_TM_PG_PATTERN_PREFIX
, limit
) >=
778 } else if (pg
!= NULL
&& type
!= NULL
) {
779 size
= snprintf(name
, limit
, "%s%s",
780 SCF_PG_TM_PG_PATTERN_NT_PREFIX
, pg
);
781 } else if (pg
!= NULL
&& type
== NULL
&& use_type
== 1) {
782 size
= snprintf(name
, limit
, "%s%s",
783 SCF_PG_TM_PG_PATTERN_NT_PREFIX
, pg
);
784 } else if (pg
!= NULL
&& type
== NULL
) {
785 size
= snprintf(name
, limit
, "%s%s",
786 SCF_PG_TM_PG_PATTERN_N_PREFIX
, pg
);
787 } else if (type
!= NULL
&& pg
== NULL
) {
788 size
= snprintf(name
, limit
, "%s%s",
789 SCF_PG_TM_PG_PATTERN_T_PREFIX
, type
);
796 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
806 * Gets the name of the supplied property group. On success, returns an
807 * allocated string. The string must be freed by free().
809 * Returns NULL on failure and sets scf_error() to _CONNECTION_BROKEN,
810 * _DELETED, or _NO_MEMORY.
813 _scf_get_pg_name(scf_propertygroup_t
*pg
)
815 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
816 char *buf
= malloc(sz
);
819 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
820 } else if (scf_pg_get_name(pg
, buf
, sz
) == -1) {
821 if (ismember(scf_error(), errors_server
)) {
834 * char *_tmpl_prop_name()
836 * Returns the name of the property template prop (which is the name of
837 * the property template property group) in the property group
838 * template t. Returns NULL on failure and sets scf_error() to:
839 * SCF_ERROR_CONNECTION_BROKEN
841 * SCF_ERROR_INVALID_ARGUMENT
842 * can't combine the arguments and get a reasonable length name
843 * SCF_ERROR_NO_MEMORY
846 _tmpl_prop_name(const char *prop
, scf_pg_tmpl_t
*t
)
848 char *name
= NULL
, *pg_name
= NULL
;
850 ssize_t limit
, size
= 0;
852 assert(prop
!= NULL
);
853 assert(t
->pt_pg
!= NULL
);
855 limit
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
856 name
= malloc(limit
);
858 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
862 if ((pg_name
= _scf_get_pg_name(t
->pt_pg
)) == NULL
) {
867 prefix_size
= strlen(SCF_PG_TM_PG_PAT_BASE
);
868 if (strncmp(pg_name
, SCF_PG_TM_PG_PAT_BASE
, prefix_size
) != 0) {
869 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
875 size
= snprintf(name
, limit
, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX
,
876 pg_name
+ prefix_size
, prop
);
879 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
890 * int _get_snapshot()
892 * Gets the specified snapshot. If "snapshot" isn't defined, use the
893 * running snapshot. If the snapshot isn't found, that may or may
894 * not be an error depending on the caller. Return 0 in that case,
895 * but leave scf_error() set to SCF_ERROR_NOT_FOUND. On all other
896 * errors, set scf_error() to:
897 * SCF_ERROR_BACKEND_ACCESS
898 * SCF_ERROR_CONNECTION_BROKEN
900 * SCF_ERR_HANDLE_DESTROYED
902 * SCF_ERROR_INVALID_ARGUMENT
903 * The handle argument is NULL, or snaphot is not a valid snapshot name
904 * SCF_ERROR_NO_MEMORY
905 * SCF_ERROR_NO_RESOURCES
906 * SCF_ERROR_NOT_BOUND
907 * SCF_ERROR_NOT_FOUND
910 _get_snapshot(scf_instance_t
*inst
, const char *snapshot
,
911 scf_snapshot_t
**snap
)
916 h
= scf_instance_handle(inst
);
922 if ((*snap
= scf_snapshot_create(h
)) == NULL
) {
926 /* Use running snapshot by default. */
927 if (snapshot
== NULL
)
928 err
= scf_instance_get_snapshot(inst
, "running", *snap
);
930 err
= scf_instance_get_snapshot(inst
, snapshot
, *snap
);
933 if (ismember(scf_error(), errors_server
)) {
934 scf_snapshot_destroy(*snap
);
937 } else switch (scf_error()) {
938 case SCF_ERROR_INVALID_ARGUMENT
:
939 scf_snapshot_destroy(*snap
);
943 case SCF_ERROR_NOT_FOUND
:
944 scf_snapshot_destroy(*snap
);
948 case SCF_ERROR_NOT_SET
:
949 case SCF_ERROR_HANDLE_MISMATCH
:
957 * Explicitly set SCF_ERROR_NONE so that the SCF_ERROR_NOT_FOUND
958 * return above is explicitly guaranteed to be from
959 * scf_instance_get_snapshot().
961 (void) scf_set_error(SCF_ERROR_NONE
);
966 * Returns NULL on error, sets scf_error() to:
967 * SCF_ERROR_BACKEND_ACCESS
968 * SCF_ERROR_CONNECTION_BROKEN
969 * SCF_ERROR_CONSTRAINT_VIOLATED
970 * The restarter's FMRI does not match an existing instance.
972 * SCF_ERROR_HANDLE_DESTROYED
974 * SCF_ERROR_INVALID_ARGUMENT
975 * The restarter's FMRI is not a valid FMRI.
976 * SCF_ERROR_NO_MEMORY
977 * SCF_ERROR_NO_RESOURCES
978 * SCF_ERROR_NOT_BOUND
979 * SCF_ERROR_NOT_FOUND
980 * Property doesn't exist or exists and has no value.
981 * SCF_ERROR_TEMPLATE_INVALID
982 * restarter property is not SCF_TYPE_ASTRING or has more than one value
984 static scf_instance_t
*
985 _get_restarter_inst(scf_handle_t
*h
, scf_service_t
*svc
,
986 scf_instance_t
*inst
, scf_snapshot_t
*s
)
988 char *restarter
= NULL
;
989 scf_instance_t
*ri
= NULL
;
990 scf_propertygroup_t
*pg
= NULL
;
993 assert(svc
!= NULL
|| inst
!= NULL
);
994 assert(svc
== NULL
|| inst
== NULL
);
996 if ((ri
= scf_instance_create(h
)) == NULL
||
997 (pg
= scf_pg_create(h
)) == NULL
) {
998 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
999 goto _get_restarter_inst_fail
;
1003 ret
= scf_instance_get_pg_composed(inst
, s
, SCF_PG_GENERAL
,
1006 ret
= scf_service_get_pg(svc
, SCF_PG_GENERAL
, pg
);
1009 if (ismember(scf_error(), errors_server
)) {
1010 goto _get_restarter_inst_fail
;
1011 } else switch (scf_error()) {
1012 case SCF_ERROR_NOT_FOUND
:
1013 /* Assume default restarter. */
1016 case SCF_ERROR_NOT_SET
:
1017 case SCF_ERROR_HANDLE_MISMATCH
:
1019 * If the arguments to the above functions
1020 * aren't derived from the same handle, there's
1021 * something wrong with the internal implementation,
1022 * not the public caller further up the chain.
1024 case SCF_ERROR_INVALID_ARGUMENT
:
1030 restarter
= _scf_read_single_astring_from_pg(pg
,
1031 SCF_PROPERTY_RESTARTER
);
1032 /* zero length string is NOT a valid restarter */
1033 if (restarter
!= NULL
&& restarter
[0] == '\0') {
1036 } else if (restarter
== NULL
) {
1037 if (ismember(scf_error(), errors_server
)) {
1038 goto _get_restarter_inst_fail
;
1039 } else switch (scf_error()) {
1040 case SCF_ERROR_NOT_FOUND
:
1043 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1044 case SCF_ERROR_TYPE_MISMATCH
:
1045 (void) scf_set_error(
1046 SCF_ERROR_TEMPLATE_INVALID
);
1047 goto _get_restarter_inst_fail
;
1049 case SCF_ERROR_NOT_SET
:
1050 case SCF_ERROR_INVALID_ARGUMENT
:
1058 if (restarter
== NULL
) {
1059 /* Use default restarter */
1060 restarter
= strdup(SCF_SERVICE_STARTD
);
1061 if (restarter
== NULL
) {
1062 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1063 goto _get_restarter_inst_fail
;
1067 if (scf_handle_decode_fmri(h
, restarter
, NULL
, NULL
, ri
, NULL
, NULL
,
1068 SCF_DECODE_FMRI_EXACT
|SCF_DECODE_FMRI_REQUIRE_INSTANCE
) != 0) {
1069 if (ismember(scf_error(), errors_server
)) {
1070 goto _get_restarter_inst_fail
;
1071 } else switch (scf_error()) {
1072 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1073 case SCF_ERROR_INVALID_ARGUMENT
:
1074 case SCF_ERROR_NOT_FOUND
:
1075 goto _get_restarter_inst_fail
;
1077 case SCF_ERROR_HANDLE_MISMATCH
:
1078 case SCF_ERROR_NOT_SET
:
1089 _get_restarter_inst_fail
:
1091 scf_instance_destroy(ri
);
1097 * Returns NULL on error, sets scf_error() to:
1098 * SCF_ERROR_BACKEND_ACCESS
1099 * SCF_ERROR_CONNECTION_BROKEN
1100 * SCF_ERROR_CONSTRAINT_VIOLATED
1101 * Restarter property has more than one value associated with it,
1102 * or FMRI does not meet restrictions in scf_handle_decode_fmri() flags.
1104 * SCF_ERROR_HANDLE_DESTROYED
1105 * SCF_ERROR_INTERNAL
1106 * SCF_ERROR_INVALID_ARGUMENT
1107 * The fmri argument in scf_handle_decode_fmri() is not a valid FMRI.
1108 * SCF_ERROR_NO_MEMORY
1109 * SCF_ERROR_NO_RESOURCES
1110 * SCF_ERROR_NOT_BOUND
1111 * SCF_ERROR_NOT_FOUND
1112 * Property doesn't exist or exists and has no value.
1114 static scf_instance_t
*
1115 _get_global_inst(scf_handle_t
*h
)
1119 if ((ri
= scf_instance_create(h
)) == NULL
) {
1120 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
1121 (void) scf_set_error(SCF_ERROR_NO_RESOURCES
);
1125 if (scf_handle_decode_fmri(h
, SCF_INSTANCE_GLOBAL
, NULL
, NULL
, ri
,
1127 SCF_DECODE_FMRI_EXACT
|SCF_DECODE_FMRI_REQUIRE_INSTANCE
) != 0) {
1128 if (ismember(scf_error(), errors_server
)) {
1129 scf_instance_destroy(ri
);
1131 } else switch (scf_error()) {
1132 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1133 case SCF_ERROR_INVALID_ARGUMENT
:
1134 case SCF_ERROR_NOT_FOUND
:
1135 scf_instance_destroy(ri
);
1138 case SCF_ERROR_HANDLE_MISMATCH
:
1139 case SCF_ERROR_NOT_SET
:
1150 * Call the supplied function for each of the service or instance, the
1151 * service's restarter, and the globally defined template instance.
1152 * If the function returns SCF_WALK_ERROR, the walk is ended. If
1153 * the function returns SCF_WALK_NEXT, the next entity is tried.
1155 * The function is only expected to return SCF_WALK_DONE if it has
1156 * found a property group match in the current entity, and has
1157 * populated p->pw_pg with the matching property group.
1159 * The caller of _walk_template_instances() MUST check if the passed parameters
1160 * inst and svc match the fields pw_inst and pw_svc in the resulting
1161 * pg_tmpl_walk_t and call the destructor for the unmatching objects. The walker
1162 * may silently drop them if the template definition is in the restarter or in
1163 * the global instance.
1166 _walk_template_instances(scf_service_t
*svc
, scf_instance_t
*inst
,
1167 scf_snapshot_t
*snap
, walk_template_inst_func_t
*func
,
1168 pg_tmpl_walk_t
*p
, int flag
)
1170 scf_instance_t
*tmpl_inst
= NULL
;
1175 assert(svc
!= NULL
|| inst
!= NULL
);
1176 assert(svc
== NULL
|| inst
== NULL
);
1179 h
= scf_instance_handle(inst
);
1181 h
= scf_service_handle(svc
);
1185 /* First, use supplied service or instance */
1186 p
->pw_target
= SCF_TM_TARGET_THIS
;
1187 ret
= func(svc
, inst
, p
);
1193 * Check that the template scoping matches and if not,
1196 assert(p
->pw_pg
!= NULL
);
1197 tg
= _scf_read_single_astring_from_pg(p
->pw_pg
,
1198 SCF_PROPERTY_TM_TARGET
);
1199 if (tg
== NULL
|| /* scf_error() was set */
1200 (strcmp(tg
, SCF_TM_TARGET_INSTANCE
) != 0 &&
1201 strcmp(tg
, SCF_TM_TARGET_THIS
) != 0 &&
1202 (flag
& SCF_PG_TMPL_FLAG_EXACT
) !=
1203 SCF_PG_TMPL_FLAG_EXACT
)) {
1204 scf_pg_destroy(p
->pw_pg
);
1213 case SCF_WALK_ERROR
:
1221 /* Next the restarter. */
1222 p
->pw_target
= SCF_TM_TARGET_DELEGATE
;
1223 tmpl_inst
= _get_restarter_inst(h
, svc
, inst
, snap
);
1224 if (tmpl_inst
!= NULL
) {
1225 ret
= func(NULL
, tmpl_inst
, p
);
1231 * Check that the template scoping matches and if not,
1234 assert(p
->pw_pg
!= NULL
);
1235 tg
= _scf_read_single_astring_from_pg(p
->pw_pg
,
1236 SCF_PROPERTY_TM_TARGET
);
1237 if (tg
== NULL
|| /* scf_error() was set */
1238 strcmp(tg
, SCF_TM_TARGET_DELEGATE
) != 0) {
1239 scf_pg_destroy(p
->pw_pg
);
1248 case SCF_WALK_ERROR
:
1257 p
->pw_target
= SCF_TM_TARGET_ALL
;
1258 scf_instance_destroy(tmpl_inst
);
1259 tmpl_inst
= _get_global_inst(h
);
1260 if (tmpl_inst
!= NULL
) {
1261 ret
= func(NULL
, tmpl_inst
, p
);
1267 * Check that the template scoping matches and if not,
1270 assert(p
->pw_pg
!= NULL
);
1271 tg
= _scf_read_single_astring_from_pg(p
->pw_pg
,
1272 SCF_PROPERTY_TM_TARGET
);
1273 if (tg
== NULL
|| /* scf_error() was set */
1274 strcmp(tg
, SCF_TM_TARGET_ALL
) != 0) {
1275 scf_pg_destroy(p
->pw_pg
);
1284 case SCF_WALK_ERROR
:
1295 if (ret
!= SCF_WALK_DONE
)
1296 scf_instance_destroy(tmpl_inst
);
1297 p
->pw_target
= NULL
;
1301 * _get_pg() returns 0 on success and -1 on failure. Sets scf_error()
1303 * SCF_ERROR_BACKEND_ACCESS
1304 * SCF_ERROR_CONNECTION_BROKEN
1306 * SCF_ERROR_HANDLE_MISMATCH
1307 * SCF_ERROR_INTERNAL
1308 * SCF_ERROR_INVALID_ARGUMENT
1309 * name is not a valid property group.
1310 * SCF_ERROR_NO_RESOURCES
1311 * SCF_ERROR_NOT_BOUND
1312 * SCF_ERROR_NOT_FOUND
1316 _get_pg(scf_service_t
*svc
, scf_instance_t
*inst
,
1317 const scf_snapshot_t
*snap
, const char *name
, scf_propertygroup_t
*pg
)
1321 assert(svc
!= NULL
|| inst
!= NULL
);
1322 assert(svc
== NULL
|| inst
== NULL
);
1326 ret
= scf_instance_get_pg_composed(inst
, snap
, name
, pg
);
1328 ret
= scf_service_get_pg(svc
, name
, pg
);
1334 * Returns SCF_WALK_NEXT for not found, SCF_WALK_ERROR for error,
1335 * and SCF_WALK_DONE for found.
1336 * On error, destroy pg and set it to NULL.
1338 * Sets scf_error() if SCF_WALK_ERROR is returned to _BACKEND_ACCESS,
1339 * _CONNECTION_BROKEN, _INTERNAL, _INVALID_ARGUMENT (name is not a
1340 * valid property group), _NO_RESOURCES, or _NOT_BOUND.
1343 _lookup_pg(scf_service_t
*svc
, scf_instance_t
*inst
,
1344 const scf_snapshot_t
*snap
, const char *name
, scf_propertygroup_t
*pg
)
1348 ret
= _get_pg(svc
, inst
, snap
, name
, pg
);
1351 return (SCF_WALK_DONE
);
1353 switch (scf_error()) {
1354 case SCF_ERROR_NOT_FOUND
:
1355 case SCF_ERROR_DELETED
:
1356 return (SCF_WALK_NEXT
);
1358 case SCF_ERROR_BACKEND_ACCESS
:
1359 case SCF_ERROR_CONNECTION_BROKEN
:
1360 case SCF_ERROR_INTERNAL
:
1361 case SCF_ERROR_INVALID_ARGUMENT
:
1362 case SCF_ERROR_NOT_BOUND
:
1363 case SCF_ERROR_NO_RESOURCES
:
1366 return (SCF_WALK_ERROR
);
1368 case SCF_ERROR_NOT_SET
:
1369 case SCF_ERROR_HANDLE_MISMATCH
:
1380 * If match, return 0. If no match, return 1. If error, return -1.
1381 * On error set scf_error() to _BACKEND_ACCESS, _CONNECTION_BROKEN,
1382 * _HANDLE_DESTROYED, _INTERNAL, _NO_MEMORY, _NO_RESOURCES, _NOT_BOUND,
1383 * _NOT_SET (property group specified by pg is not set), _PERMISSION_DENIED,
1384 * or _TEMPLATE_INVALID (target property is not SCF_TYPE_ASTRING or has
1385 * more than one value).
1388 check_target_match(scf_propertygroup_t
*pg
, const char *target
)
1393 pg_target
= _scf_read_single_astring_from_pg(pg
,
1394 SCF_PROPERTY_TM_TARGET
);
1395 if (pg_target
== NULL
) {
1396 switch (scf_error()) {
1397 case SCF_ERROR_DELETED
:
1398 case SCF_ERROR_NOT_FOUND
:
1401 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1402 case SCF_ERROR_TYPE_MISMATCH
:
1403 (void) scf_set_error(
1404 SCF_ERROR_TEMPLATE_INVALID
);
1407 case SCF_ERROR_BACKEND_ACCESS
:
1408 case SCF_ERROR_CONNECTION_BROKEN
:
1409 case SCF_ERROR_HANDLE_DESTROYED
:
1410 case SCF_ERROR_INTERNAL
:
1411 case SCF_ERROR_NO_RESOURCES
:
1412 case SCF_ERROR_NOT_BOUND
:
1413 case SCF_ERROR_PERMISSION_DENIED
:
1416 case SCF_ERROR_NOT_SET
:
1417 case SCF_ERROR_INVALID_ARGUMENT
:
1425 /* For a desired target of 'this', check for 'this' and 'instance'. */
1426 if ((strcmp(target
, SCF_TM_TARGET_INSTANCE
) == 0 ||
1427 strcmp(target
, SCF_TM_TARGET_THIS
) == 0) &&
1428 (strcmp(pg_target
, SCF_TM_TARGET_INSTANCE
) == 0 ||
1429 strcmp(pg_target
, SCF_TM_TARGET_THIS
) == 0)) {
1433 if (strcmp(target
, SCF_TM_TARGET_DELEGATE
) == 0 &&
1434 strcmp(pg_target
, SCF_TM_TARGET_DELEGATE
) == 0) {
1438 if (strcmp(target
, SCF_TM_TARGET_ALL
) == 0 &&
1439 strcmp(pg_target
, SCF_TM_TARGET_ALL
) == 0) {
1450 * Check if a matching template property group exists for each of:
1451 * name and type, name only, type only, and completely wildcarded
1454 * Both pg_name and pg_type are optional.
1456 * Returns NULL on failure, sets scf_error():
1457 * SCF_ERROR_BACKEND_ACCESS
1458 * SCF_ERROR_CONNECTION_BROKEN
1460 * SCF_ERROR_HANDLE_DESTROYED
1461 * SCF_ERROR_INTERNAL
1462 * SCF_ERROR_INVALID_ARGUMENT
1463 * can't combine the _tmpl_pg_name arguments and get a reasonable
1464 * length name, or pg_name is not a valid property group.
1465 * SCF_ERROR_NO_MEMORY
1466 * SCF_ERROR_NO_RESOURCES
1467 * SCF_ERROR_NOT_BOUND
1468 * SCF_ERROR_NOT_FOUND
1469 * Property doesn't exist or exists and has no value.
1470 * SCF_ERROR_PERMISSION_DENIED
1471 * SCF_ERROR_TEMPLATE_INVALID
1472 * target property is not SCF_TYPE_ASTRING or has more than one value.
1474 static scf_propertygroup_t
*
1475 _find_template_pg_match(scf_service_t
*svc
, scf_instance_t
*inst
,
1476 const scf_snapshot_t
*snap
, const char *pg_name
, const char *pg_type
,
1477 const char *target
, char **tmpl_pg_name
)
1480 scf_propertygroup_t
*pg
= NULL
;
1485 assert(inst
!= NULL
|| svc
!= NULL
);
1486 assert(inst
== NULL
|| svc
== NULL
);
1489 h
= scf_instance_handle(inst
);
1491 h
= scf_service_handle(svc
);
1496 if ((pg
= scf_pg_create(h
)) == NULL
||
1497 (iter
= scf_iter_create(h
)) == NULL
) {
1498 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
1504 * We're going to walk through the possible pg templates that
1505 * could match the supplied name and type. We do this
1506 * by explicit name lookups when possible to avoid having to
1507 * keep track of a most-explicit-match during iteration.
1510 /* First look for a template with name and type set and matching. */
1511 *tmpl_pg_name
= _tmpl_pg_name(pg_name
, pg_type
, 1);
1512 if (*tmpl_pg_name
== NULL
)
1514 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1515 if (ret
!= SCF_WALK_NEXT
) {
1517 if ((r
= check_target_match(pg
, target
)) == 0)
1525 free(*tmpl_pg_name
);
1528 * Need to search on a name-only match before searching on
1532 *tmpl_pg_name
= _tmpl_pg_name(pg_name
, NULL
, 0);
1533 if (*tmpl_pg_name
== NULL
)
1535 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1536 if (ret
!= SCF_WALK_NEXT
) {
1538 if ((r
= check_target_match(pg
, target
)) == 0)
1546 free(*tmpl_pg_name
);
1548 /* Next, see if there's an "nt" template where the type matches. */
1549 if (pg_type
!= NULL
&& pg_name
== NULL
) {
1551 ret
= scf_iter_instance_pgs_typed_composed(iter
, inst
,
1552 snap
, SCF_GROUP_TEMPLATE_PG_PATTERN
);
1554 ret
= scf_iter_service_pgs_typed(iter
, svc
,
1555 SCF_GROUP_TEMPLATE_PG_PATTERN
);
1558 if (ismember(scf_error(), errors_server
)) {
1566 while ((ret
= scf_iter_next_pg(iter
, pg
)) == 1) {
1567 /* Make sure this is a name and type specified pg. */
1568 name
= _scf_read_single_astring_from_pg(pg
,
1569 SCF_PROPERTY_TM_NAME
);
1572 type
= _scf_read_single_astring_from_pg(pg
,
1573 SCF_PROPERTY_TM_TYPE
);
1578 if (strcmp(pg_type
, type
) == 0 &&
1579 check_target_match(pg
, target
) == 0) {
1580 *tmpl_pg_name
= name
;
1588 if (ismember(scf_error(), errors_server
)) {
1597 *tmpl_pg_name
= _tmpl_pg_name(NULL
, pg_type
, 0);
1598 if (*tmpl_pg_name
== NULL
)
1600 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1601 if (ret
!= SCF_WALK_NEXT
) {
1603 if ((r
= check_target_match(pg
, target
)) == 0)
1611 free(*tmpl_pg_name
);
1613 *tmpl_pg_name
= _tmpl_pg_name(NULL
, NULL
, 0);
1614 if (*tmpl_pg_name
== NULL
)
1616 ret
= _lookup_pg(svc
, inst
, snap
, *tmpl_pg_name
, pg
);
1617 if (ret
!= SCF_WALK_NEXT
) {
1619 if ((r
= check_target_match(pg
, target
)) == 0)
1628 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
1631 if (*tmpl_pg_name
!= NULL
)
1632 free(*tmpl_pg_name
);
1633 *tmpl_pg_name
= NULL
;
1636 if (ret
== SCF_WALK_ERROR
)
1637 free(*tmpl_pg_name
);
1638 scf_iter_destroy(iter
);
1643 * Finds the pg match in either the supplied service or instance.
1644 * Returns SCF_WALK_ERROR, SCF_WALK_NEXT, or SCF_WALK_DONE.
1645 * If returning SCF_WALK_ERROR, sets scf_error():
1646 * SCF_ERROR_BACKEND_ACCESS
1647 * SCF_ERROR_CONNECTION_BROKEN
1649 * SCF_ERROR_HANDLE_DESTROYED
1650 * SCF_ERROR_INTERNAL
1651 * SCF_ERROR_INVALID_ARGUMENT
1652 * The snaphot is not a valid snapshot name,
1653 * or can't create a reasonable property group template name.
1654 * SCF_ERROR_NO_MEMORY
1655 * SCF_ERROR_NO_RESOURCES
1656 * SCF_ERROR_NOT_BOUND
1657 * SCF_ERROR_NOT_FOUND
1658 * Property doesn't exist or exists and has no value.
1659 * SCF_ERROR_PERMISSION_DENIED
1660 * SCF_ERROR_TEMPLATE_INVALID
1661 * target property is not SCF_TYPE_ASTRING or has more than one value.
1664 find_pg_match(scf_service_t
*svc
, scf_instance_t
*inst
, pg_tmpl_walk_t
*p
)
1666 scf_snapshot_t
*tmpl_snap
= NULL
;
1667 scf_propertygroup_t
*pg
;
1671 assert(svc
!= NULL
|| inst
!= NULL
);
1672 assert(svc
== NULL
|| inst
== NULL
);
1675 h
= scf_instance_handle(inst
);
1677 h
= scf_service_handle(svc
);
1679 return (SCF_WALK_ERROR
);
1681 if (p
->pw_snapname
!= NULL
) {
1682 if (_get_snapshot(inst
, p
->pw_snapname
, &tmpl_snap
) == -1)
1683 return (SCF_WALK_ERROR
);
1685 pg
= _find_template_pg_match(svc
, inst
, tmpl_snap
, p
->pw_pgname
,
1686 p
->pw_pgtype
, p
->pw_target
, &tmpl_pg_name
);
1689 p
->pw_snap
= tmpl_snap
;
1691 p
->pw_tmpl_pgname
= tmpl_pg_name
;
1694 return (SCF_WALK_DONE
);
1697 scf_snapshot_destroy(tmpl_snap
);
1698 return (SCF_WALK_NEXT
);
1702 * return 0 on success and -1 on failure.
1703 * SCF_ERROR_CONNECTION_BROKEN
1705 * SCF_ERROR_HANDLE_DESTROYED
1706 * SCF_ERROR_HANDLE_MISMATCH
1707 * SCF_ERROR_INTERNAL
1708 * SCF_ERROR_INVALID_ARGUMENT
1709 * FMRI argument, snapshot name, pg_name, or pg is invalid.
1710 * SCF_ERROR_NO_MEMORY
1711 * SCF_ERROR_NO_RESOURCES
1712 * SCF_ERROR_NOT_BOUND
1713 * SCF_ERROR_NOT_FOUND
1717 scf_tmpl_get_by_pg(scf_propertygroup_t
*pg
, scf_pg_tmpl_t
*pg_tmpl
, int flags
)
1719 char *fmribuf
= NULL
, *snapbuf
= NULL
, *pg_name
= NULL
, *pg_type
= NULL
;
1721 ssize_t fbufsz
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
) + 1;
1722 ssize_t nbufsz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
1723 ssize_t tbufsz
= scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH
) + 1;
1724 scf_instance_t
*inst
= NULL
;
1725 scf_snaplevel_t
*snaplvl
= NULL
;
1726 scf_service_t
*svc
= NULL
;
1728 scf_snapshot_t
*snap
= NULL
;
1729 pg_tmpl_walk_t
*p
= NULL
;
1731 assert(fbufsz
!= 0 && nbufsz
!= 0 && tbufsz
!= 0);
1733 scf_tmpl_pg_reset(pg_tmpl
);
1735 if ((h
= scf_pg_handle(pg
)) == NULL
)
1738 if ((inst
= scf_instance_create(h
)) == NULL
||
1739 (svc
= scf_service_create(h
)) == NULL
||
1740 (snaplvl
= scf_snaplevel_create(h
)) == NULL
) {
1744 if ((fmribuf
= malloc(fbufsz
)) == NULL
||
1745 (pg_name
= malloc(nbufsz
)) == NULL
||
1746 (pg_type
= malloc(tbufsz
)) == NULL
||
1747 (p
= calloc(1, sizeof (pg_tmpl_walk_t
))) == NULL
) {
1748 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1752 if (scf_pg_get_name(pg
, pg_name
, nbufsz
) < 0) {
1756 if (scf_pg_get_type(pg
, pg_type
, tbufsz
) < 0) {
1759 p
->pw_pgname
= pg_name
;
1760 p
->pw_pgtype
= pg_type
;
1762 ret
= scf_pg_get_parent_snaplevel(pg
, snaplvl
);
1764 switch (scf_error()) {
1765 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1766 /* Parent type doesn't match. Keep looking. */
1769 case SCF_ERROR_DELETED
:
1770 case SCF_ERROR_NOT_BOUND
:
1771 case SCF_ERROR_NOT_SET
:
1772 /* Pass these back to the caller. */
1775 case SCF_ERROR_HANDLE_MISMATCH
:
1782 * No snapshot. We'll use 'editing' by default since
1783 * snap and snapbuf are NULL.
1785 p
->pw_snapname
= NULL
;
1788 if ((snap
= scf_snapshot_create(h
)) == NULL
) {
1792 ret
= scf_snaplevel_get_parent(snaplvl
, snap
);
1794 if (ismember(scf_error(), errors_server
)) {
1802 /* Grab snapshot name while we're here. */
1803 if ((snapbuf
= malloc(nbufsz
)) == NULL
) {
1804 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1807 if (scf_snapshot_get_name(snap
, snapbuf
, nbufsz
) < 0) {
1808 if (ismember(scf_error(), errors_server
)) {
1815 p
->pw_snapname
= snapbuf
;
1817 ret
= scf_snapshot_get_parent(snap
, inst
);
1819 if (ismember(scf_error(), errors_server
)) {
1827 _walk_template_instances(NULL
, inst
, snap
,
1828 (walk_template_inst_func_t
*)find_pg_match
, p
, flags
);
1831 /* No snapshot parent. Go looking for instance parent. */
1832 if (snapbuf
== NULL
) {
1833 /* First look for instance parent. */
1834 ret
= scf_pg_get_parent_instance(pg
, inst
);
1836 _walk_template_instances(NULL
, inst
, snap
,
1837 (walk_template_inst_func_t
*)find_pg_match
,
1839 /* OK, check for service parent */
1840 } else if (ret
== -1 &&
1841 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
1842 ret
= scf_pg_get_parent_service(pg
, svc
);
1844 _walk_template_instances(svc
, NULL
, snap
,
1845 (walk_template_inst_func_t
*)find_pg_match
,
1848 switch (scf_error()) {
1849 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1850 (void) scf_set_error(
1851 SCF_ERROR_NOT_FOUND
);
1854 case SCF_ERROR_CONNECTION_BROKEN
:
1855 case SCF_ERROR_DELETED
:
1856 case SCF_ERROR_HANDLE_MISMATCH
:
1857 case SCF_ERROR_NOT_BOUND
:
1858 case SCF_ERROR_NOT_SET
:
1871 if (p
->pw_pg
!= NULL
) {
1873 pg_tmpl
->pt_pg
= p
->pw_pg
;
1874 pg_tmpl
->pt_inst
= p
->pw_inst
;
1875 /* we may get a different instance back */
1876 if (p
->pw_inst
!= inst
)
1877 scf_instance_destroy(inst
);
1878 pg_tmpl
->pt_snap
= p
->pw_snap
;
1879 pg_tmpl
->pt_svc
= p
->pw_svc
;
1880 /* we may get a different service back */
1881 if (p
->pw_svc
!= svc
)
1882 scf_service_destroy(svc
);
1883 pg_tmpl
->pt_populated
= 1;
1884 free(p
->pw_tmpl_pgname
);
1889 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
1893 scf_instance_destroy(inst
);
1894 scf_service_destroy(svc
);
1896 scf_snapshot_destroy(snap
);
1902 scf_snaplevel_destroy(snaplvl
);
1907 * int scf_tmpl_get_by_pg_name()
1909 * Get a template by a combination of the name and type. Either name
1910 * or type can be null, which indicates a wildcard. flags may be
1911 * SCF_PG_TMPL_FLAG_CURRENT (use current properties rather than
1912 * the defined or running snapshot), and SCF_PG_TMPL_FLAG_EXACT (match
1913 * only templates defined by the FMRI in question, not by its restarter
1914 * or globally). Returns 0 on success and -1 on error, and sets
1916 * SCF_ERROR_BACKEND_ACCESS
1917 * SCF_ERROR_CONNECTION_BROKEN
1918 * The connection to the repository was lost.
1920 * The instance has been deleted.
1921 * SCF_ERROR_HANDLE_DESTROYED
1922 * SCF_ERROR_INTERNAL
1923 * SCF_ERROR_INVALID_ARGUMENT
1924 * FMRI isn't valid, pg_name is too long to look for a template, or
1925 * snapshot specified isn't a valid name
1926 * SCF_ERROR_NO_MEMORY
1927 * SCF_ERROR_NO_RESOURCES
1928 * The server does not have adequate resources to complete the request.
1929 * SCF_ERROR_NOT_BOUND
1930 * The handle is not currently bound.
1931 * SCF_ERROR_NOT_FOUND
1932 * Object matching FMRI doesn't exist in the repository, or snapshot
1936 scf_tmpl_get_by_pg_name(const char *fmri
, const char *snapshot
,
1937 const char *pg_name
, const char *pg_type
, scf_pg_tmpl_t
*pg_tmpl
, int flags
)
1939 scf_instance_t
*inst
= NULL
;
1940 scf_service_t
*svc
= NULL
;
1941 scf_snapshot_t
*snap
= NULL
;
1942 pg_tmpl_walk_t
*p
= NULL
;
1946 assert(pg_tmpl
!= NULL
);
1950 scf_tmpl_pg_reset(pg_tmpl
);
1952 if ((inst
= scf_instance_create(h
)) == NULL
||
1953 (svc
= scf_service_create(h
)) == NULL
) {
1957 p
= calloc(1, sizeof (pg_tmpl_walk_t
));
1959 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1963 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, inst
, NULL
,
1964 NULL
, SCF_DECODE_FMRI_EXACT
);
1966 scf_service_destroy(svc
);
1968 } else if (ret
!= 0 &&
1969 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
1970 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, svc
,
1971 NULL
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
);
1973 scf_instance_destroy(inst
);
1978 if (ismember(scf_error(), errors_server
)) {
1980 } else switch (scf_error()) {
1981 case SCF_ERROR_CONSTRAINT_VIOLATED
:
1982 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1985 case SCF_ERROR_INVALID_ARGUMENT
:
1986 case SCF_ERROR_NOT_FOUND
:
1989 case SCF_ERROR_HANDLE_MISMATCH
:
1990 case SCF_ERROR_NOT_SET
:
1997 assert(svc
== NULL
|| inst
== NULL
);
1998 assert(svc
!= NULL
|| inst
!= NULL
);
2000 /* If we have a service fmri, snapshot is ignored. */
2002 if (snapshot
== NULL
|| strcmp(snapshot
, "running") == 0 ||
2003 (flags
& SCF_PG_TMPL_FLAG_CURRENT
) ==
2004 SCF_PG_TMPL_FLAG_CURRENT
) {
2005 if (_get_snapshot(inst
, NULL
, &snap
) == -1)
2008 if (_get_snapshot(inst
, snapshot
, &snap
) == -1) {
2010 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2016 p
->pw_snapname
= snapshot
;
2017 p
->pw_pgname
= pg_name
;
2018 p
->pw_pgtype
= pg_type
;
2021 * For each of instance, restarter, global
2022 * - check for a tm_pg_pattern_nt_<name> matching type
2023 * - check for a tm_pg_pattern_t_<type> matching type
2024 * - check for any tm_pg_pattern_
2025 * Currently plan to return the most specific match only.
2027 _walk_template_instances(svc
, inst
, snap
,
2028 (walk_template_inst_func_t
*)find_pg_match
, p
, flags
);
2030 if (p
->pw_pg
!= NULL
) {
2032 pg_tmpl
->pt_pg
= p
->pw_pg
;
2033 pg_tmpl
->pt_inst
= p
->pw_inst
;
2034 /* we may get a different instance back */
2035 if (p
->pw_inst
!= inst
)
2036 scf_instance_destroy(inst
);
2037 pg_tmpl
->pt_snap
= p
->pw_snap
;
2038 pg_tmpl
->pt_svc
= p
->pw_svc
;
2039 /* we may get a different service back */
2040 if (p
->pw_svc
!= svc
)
2041 scf_service_destroy(svc
);
2042 pg_tmpl
->pt_populated
= 1;
2043 scf_snapshot_destroy(snap
);
2044 free(p
->pw_tmpl_pgname
);
2049 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
2052 scf_instance_destroy(inst
);
2053 scf_service_destroy(svc
);
2054 scf_snapshot_destroy(snap
);
2059 * Returns NULL on failure, sets scf_error() to _CONNECTION_BROKEN,
2060 * _DELETED, _NO_RESOURCES, or _NOT_BOUND.
2063 _get_svc_or_inst_iter(scf_handle_t
*h
, scf_pg_tmpl_t
*t
)
2068 assert(t
->pt_svc
!= NULL
|| t
->pt_inst
!= NULL
);
2069 assert(t
->pt_svc
== NULL
|| t
->pt_inst
== NULL
);
2071 if ((iter
= scf_iter_create(h
)) == NULL
) {
2075 /* Iterate on property groups of type template_pg_pattern */
2077 if (t
->pt_inst
!= NULL
)
2078 ret
= scf_iter_instance_pgs_typed_composed(iter
,
2079 t
->pt_inst
, t
->pt_snap
,
2080 SCF_GROUP_TEMPLATE_PG_PATTERN
);
2081 if (t
->pt_svc
!= NULL
)
2082 ret
= scf_iter_service_pgs_typed(iter
, t
->pt_svc
,
2083 SCF_GROUP_TEMPLATE_PG_PATTERN
);
2086 if (ismember(scf_error(), errors_server
)) {
2087 scf_iter_destroy(iter
);
2099 * Returns NULL on failure, sets scf_error() to:
2100 * SCF_ERROR_BACKEND_ACCESS
2101 * SCF_ERROR_CONNECTION_BROKEN
2103 * SCF_HANDLE_DESTROYED
2104 * SCF_ERROR_INTERNAL
2105 * SCF_ERROR_INVALID_ARGUMENT
2106 * Handle argument is NULL, or snaphot is not a valid snapshot name.
2107 * SCF_ERROR_NO_MEMORY
2108 * SCF_ERROR_NO_RESOURCES
2109 * SCF_ERROR_NOT_BOUND
2110 * SCF_ERROR_NOT_FOUND
2113 _get_next_iterator(scf_handle_t
*h
, scf_pg_tmpl_t
*t
, const char *snapshot
,
2116 scf_iter_t
*iter
= NULL
;
2119 limit
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
2123 * Check what level we last iterated on: none, service,
2124 * restarter, or global. Make sure that if one in the middle
2125 * doesn't exist, we move on to the next entity.
2127 * Before we drop any references to pt_inst or pt_svc we must
2128 * destroy them so we don't leak them.
2131 switch (t
->pt_iter_last
) {
2132 case SCF__TMPL_ITER_NONE
:
2133 t
->pt_iter_last
= SCF__TMPL_ITER_INST
;
2134 if (t
->pt_inst
!= t
->pt_orig_inst
)
2135 scf_instance_destroy(t
->pt_inst
);
2136 t
->pt_inst
= t
->pt_orig_inst
;
2137 if (t
->pt_svc
!= t
->pt_orig_svc
)
2138 scf_service_destroy(t
->pt_svc
);
2139 t
->pt_svc
= t
->pt_orig_svc
;
2142 case SCF__TMPL_ITER_INST
:
2144 * Don't go any further than the specified instance
2148 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
2151 t
->pt_iter_last
= SCF__TMPL_ITER_RESTARTER
;
2152 if (t
->pt_inst
!= t
->pt_orig_inst
)
2153 scf_instance_destroy(t
->pt_inst
);
2154 t
->pt_inst
= _get_restarter_inst(h
, t
->pt_orig_svc
,
2155 t
->pt_orig_inst
, t
->pt_snap
);
2156 if (t
->pt_svc
!= t
->pt_orig_svc
)
2157 scf_service_destroy(t
->pt_svc
);
2161 case SCF__TMPL_ITER_RESTARTER
:
2162 t
->pt_iter_last
= SCF__TMPL_ITER_GLOBAL
;
2163 if (t
->pt_inst
!= t
->pt_orig_inst
)
2164 scf_instance_destroy(t
->pt_inst
);
2165 t
->pt_inst
= _get_global_inst(h
);
2166 if (t
->pt_svc
!= t
->pt_orig_svc
)
2167 scf_service_destroy(t
->pt_svc
);
2171 case SCF__TMPL_ITER_GLOBAL
:
2172 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
2179 } while (t
->pt_inst
== NULL
&& t
->pt_svc
== NULL
);
2181 /* Set pt_snap to the snapshot for this instance */
2182 if (t
->pt_inst
!= NULL
) {
2183 scf_snapshot_destroy(t
->pt_snap
);
2184 if (_get_snapshot(t
->pt_inst
, snapshot
,
2189 iter
= _get_svc_or_inst_iter(h
, t
);
2195 * scf_pg_tmpl_t *scf_tmpl_pg_create(scf_handle_t *)
2197 * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT
2201 scf_tmpl_pg_create(scf_handle_t
*handle
)
2203 scf_pg_tmpl_t
*pg_tmpl
= NULL
;
2205 if (handle
== NULL
) {
2206 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2209 pg_tmpl
= calloc(1, sizeof (scf_pg_tmpl_t
));
2210 if (pg_tmpl
== NULL
)
2211 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2213 pg_tmpl
->pt_h
= handle
;
2219 * Retrieves name or type of a template pg.
2220 * Returns -1 on failure. Sets scf_error():
2221 * SCF_ERROR_BACKEND_ACCESS
2222 * SCF_ERROR_CONNECTION_BROKEN
2224 * SCF_ERROR_HANDLE_DESTROYED
2225 * SCF_ERROR_INTERNAL
2226 * SCF_ERROR_NO_MEMORY
2227 * SCF_ERROR_NO_RESOURCES
2228 * SCF_ERROR_NOT_BOUND
2229 * SCF_ERROR_PERMISSION_DENIED
2230 * SCF_ERROR_TEMPLATE_INVALID
2231 * pname property is not SCF_TYPE_ASTRING or has more than one value.
2234 _scf_tmpl_prop_value(scf_propertygroup_t
*pg
, const char *pname
, char **out
)
2236 assert(strcmp(pname
, SCF_PROPERTY_TM_NAME
) == 0 ||
2237 strcmp(pname
, SCF_PROPERTY_TM_TYPE
) == 0);
2239 *out
= _scf_read_single_astring_from_pg(pg
, pname
);
2241 if (*out
!= NULL
&& *out
[0] == '\0') {
2242 (void) scf_set_error(SCF_ERROR_NONE
);
2244 *out
= strdup(SCF_TMPL_WILDCARD
);
2246 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2249 if (ismember(scf_error(), errors_server
)) {
2251 } else switch (scf_error()) {
2252 case SCF_ERROR_CONSTRAINT_VIOLATED
:
2253 case SCF_ERROR_NOT_FOUND
:
2254 case SCF_ERROR_TYPE_MISMATCH
:
2255 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
2258 case SCF_ERROR_INVALID_ARGUMENT
:
2259 case SCF_ERROR_NOT_SET
:
2266 return (strlen(*out
));
2270 * int scf_tmpl_iter_pgs()
2272 * Iterates through the property group templates for the fmri given.
2273 * When t is uninitialized or reset, sets t to the first property group
2274 * template in fmri. On subsequent calls, sets t to the next property group
2276 * Returns 1 on success, 0 when no property group templates are left to
2277 * iterate, -1 on error.
2278 * The flags argument may include SCF_PG_TMPL_FLAG_REQUIRED,
2279 * SCF_PG_TMPL_FLAG_CURRENT, and/or SCF_PG_TMPL_FLAG_EXACT.
2281 * Returns -1 on error and sets scf_error() to:
2282 * SCF_ERROR_BACKEND_ACCESS
2283 * SCF_ERROR_CONNECTION_BROKEN
2285 * SCF_ERROR_HANDLE_DESTROYED
2286 * SCF_ERROR_INTERNAL
2287 * SCF_ERROR_INVALID_ARGUMENT
2288 * The handle argument is NULL, fmri is invalid, or snapshot is invalid.
2289 * SCF_ERROR_NO_MEMORY
2290 * SCF_ERROR_NO_RESOURCES
2291 * SCF_ERROR_NOT_BOUND
2292 * SCF_ERROR_NOT_FOUND
2293 * SCF_ERROR_PERMISSION_DENIED
2296 scf_tmpl_iter_pgs(scf_pg_tmpl_t
*t
, const char *fmri
, const char *snapshot
,
2297 const char *type
, int flags
)
2300 scf_service_t
*svc
= NULL
;
2301 scf_instance_t
*inst
= NULL
;
2302 scf_propertygroup_t
*pg
= NULL
;
2303 scf_snapshot_t
*snap
= NULL
;
2304 scf_pg_tmpl_t
*pg_tmpl
= NULL
;
2312 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2318 if (t
->pt_populated
== 0) {
2319 if ((svc
= scf_service_create(h
)) == NULL
||
2320 (inst
= scf_instance_create(h
)) == NULL
||
2321 (pg
= scf_pg_create(h
)) == NULL
) {
2322 goto fail_non_populated
;
2325 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, inst
, NULL
,
2326 NULL
, SCF_DECODE_FMRI_EXACT
);
2328 scf_service_destroy(svc
);
2330 } else if (ret
!= 0 &&
2331 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
2332 ret
= scf_handle_decode_fmri(h
, fmri
, NULL
, svc
,
2333 NULL
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
);
2335 scf_instance_destroy(inst
);
2341 if (ismember(scf_error(), errors_server
)) {
2342 goto fail_non_populated
;
2343 } else switch (scf_error()) {
2344 case SCF_ERROR_CONSTRAINT_VIOLATED
:
2345 (void) scf_set_error(
2346 SCF_ERROR_INVALID_ARGUMENT
);
2347 goto fail_non_populated
;
2349 case SCF_ERROR_INVALID_ARGUMENT
:
2350 case SCF_ERROR_NOT_FOUND
:
2351 goto fail_non_populated
;
2353 case SCF_ERROR_HANDLE_MISMATCH
:
2354 case SCF_ERROR_NOT_SET
:
2361 assert(svc
== NULL
|| inst
== NULL
);
2362 assert(svc
!= NULL
|| inst
!= NULL
);
2365 if (snapshot
== NULL
||
2366 strcmp(snapshot
, "running") == 0 ||
2367 (flags
& SCF_PG_TMPL_FLAG_CURRENT
) ==
2368 SCF_PG_TMPL_FLAG_CURRENT
) {
2369 if (_get_snapshot(inst
, NULL
, &snap
) == -1)
2370 goto fail_non_populated
;
2372 (void) scf_set_error(SCF_ERROR_NONE
);
2373 if (_get_snapshot(inst
, snapshot
,
2375 goto fail_non_populated
;
2376 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2377 goto fail_non_populated
;
2381 scf_snapshot_destroy(snap
);
2386 pg_tmpl
->pt_orig_inst
= inst
;
2387 pg_tmpl
->pt_orig_svc
= svc
;
2388 pg_tmpl
->pt_snap
= snap
;
2389 pg_tmpl
->pt_is_iter
= 1;
2390 pg_tmpl
->pt_iter_last
= SCF__TMPL_ITER_NONE
;
2391 pg_tmpl
->pt_pg
= pg
;
2392 pg_tmpl
->pt_populated
= 1;
2394 if (t
->pt_is_iter
!= 1) {
2395 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2399 assert(pg_tmpl
->pt_pg
!= NULL
);
2402 if (pg_tmpl
->pt_iter
== NULL
) {
2403 pg_tmpl
->pt_iter
= _get_next_iterator(h
, pg_tmpl
, snapshot
,
2404 (flags
& SCF_PG_TMPL_FLAG_EXACT
) ? 1 : 0);
2405 if (pg_tmpl
->pt_iter
== NULL
) {
2406 if (scf_error() == SCF_ERROR_NOT_FOUND
)
2413 while (found
== 0) {
2414 while ((err
= scf_iter_next_pg(pg_tmpl
->pt_iter
,
2415 pg_tmpl
->pt_pg
)) != 1) {
2417 if (ismember(scf_error(), errors_server
)) {
2419 } else switch (scf_error()) {
2420 case SCF_ERROR_HANDLE_MISMATCH
:
2423 case SCF_ERROR_NOT_SET
:
2424 case SCF_ERROR_INVALID_ARGUMENT
:
2429 } else if (err
== 0) {
2430 /* This iteration is done. Get the next one */
2431 scf_iter_destroy(pg_tmpl
->pt_iter
);
2432 pg_tmpl
->pt_iter
= _get_next_iterator(h
,
2434 (flags
& SCF_PG_TMPL_FLAG_EXACT
) ? 1 : 0);
2435 if (pg_tmpl
->pt_iter
== NULL
) {
2436 if (scf_error() == SCF_ERROR_NOT_FOUND
)
2449 * Discard pgs which don't exist at the right scoping. This
2450 * check also makes sure that if we're looking at, for
2451 * example, svc:/system/svc/restarter:default, that we
2452 * don't hand back the same property groups twice.
2454 switch (t
->pt_iter_last
) {
2455 case SCF__TMPL_ITER_INST
:
2456 ret
= check_target_match(pg_tmpl
->pt_pg
,
2457 SCF_TM_TARGET_THIS
);
2459 case SCF__TMPL_ITER_RESTARTER
:
2460 ret
= check_target_match(pg_tmpl
->pt_pg
,
2461 SCF_TM_TARGET_DELEGATE
);
2463 case SCF__TMPL_ITER_GLOBAL
:
2464 ret
= check_target_match(pg_tmpl
->pt_pg
,
2467 case SCF__TMPL_ITER_NONE
:
2477 * If walking only required property groups, check if
2478 * the retrieved group is required.
2480 if (flags
& SCF_PG_TMPL_FLAG_REQUIRED
) {
2481 if (scf_tmpl_pg_required(pg_tmpl
, &required
) == 0) {
2490 * If type != NULL, check if type property matches. If no
2491 * type property exists, consider it a match.
2494 if (scf_tmpl_pg_type(pg_tmpl
, &tmpl_type
) != -1) {
2495 if (strcmp(tmpl_type
, SCF_TMPL_WILDCARD
)
2496 == 0 || strcmp(type
, tmpl_type
) == 0) {
2501 } else if (scf_error() == SCF_ERROR_NOT_FOUND
||
2502 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
||
2503 scf_error() == SCF_ERROR_TYPE_MISMATCH
) {
2516 scf_service_destroy(svc
);
2517 scf_instance_destroy(inst
);
2519 scf_snapshot_destroy(snap
);
2524 scf_tmpl_pg_destroy(scf_pg_tmpl_t
*t
)
2529 scf_pg_destroy(t
->pt_pg
);
2530 scf_instance_destroy(t
->pt_inst
);
2531 if (t
->pt_inst
!= t
->pt_orig_inst
)
2532 scf_instance_destroy(t
->pt_orig_inst
);
2533 scf_snapshot_destroy(t
->pt_snap
);
2534 scf_service_destroy(t
->pt_orig_svc
);
2535 if (t
->pt_svc
!= t
->pt_orig_svc
)
2536 scf_service_destroy(t
->pt_svc
);
2537 scf_iter_destroy(t
->pt_iter
);
2542 scf_tmpl_pg_reset(scf_pg_tmpl_t
*t
)
2544 scf_pg_destroy(t
->pt_pg
);
2547 scf_instance_destroy(t
->pt_inst
);
2548 if (t
->pt_inst
!= t
->pt_orig_inst
)
2549 scf_instance_destroy(t
->pt_orig_inst
);
2551 t
->pt_orig_inst
= NULL
;
2553 scf_snapshot_destroy(t
->pt_snap
);
2556 scf_service_destroy(t
->pt_orig_svc
);
2557 if (t
->pt_svc
!= t
->pt_orig_svc
)
2558 scf_service_destroy(t
->pt_svc
);
2559 t
->pt_orig_svc
= NULL
;
2562 scf_iter_destroy(t
->pt_iter
);
2565 t
->pt_populated
= 0;
2567 t
->pt_iter_last
= 0;
2569 /* Do not reset t->pt_h. */
2573 * int scf_tmpl_get_by_prop()
2575 * Get the property template given a property group template and property
2576 * name. No flags are currently defined for this function.
2578 * Returns NULL on failure, and sets scf_error():
2579 * SCF_ERROR_BACKEND_ACCESS
2580 * SCF_ERROR_CONNECTION_BROKEN
2582 * SCF_ERROR_HANDLE_DESTROYED
2583 * SCF_ERROR_INTERNAL
2584 * SCF_ERROR_INVALID_ARGUMENT
2585 * SCF_ERROR_NO_MEMORY
2586 * SCF_ERROR_NO_RESOURCES
2587 * SCF_ERROR_NOT_BOUND
2588 * SCF_ERROR_NOT_FOUND
2589 * Template object matching property doesn't exist in the repository.
2590 * SCF_ERROR_TYPE_MISMATCH
2591 * Matching template object is the wrong type in the repository.
2594 scf_tmpl_get_by_prop(scf_pg_tmpl_t
*t
, const char *prop
,
2595 scf_prop_tmpl_t
*prop_tmpl
, int flags
)
2597 char *tmpl_prop_name
;
2598 scf_propertygroup_t
*pg
= NULL
;
2603 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2607 scf_tmpl_prop_reset(prop_tmpl
);
2608 if ((pg
= scf_pg_create(scf_pg_handle(t
->pt_pg
))) == NULL
)
2611 tmpl_prop_name
= _tmpl_prop_name(prop
, t
);
2612 if (tmpl_prop_name
== NULL
) {
2613 assert(scf_error() != SCF_ERROR_NOT_SET
);
2617 if (_get_pg(t
->pt_svc
, t
->pt_inst
, t
->pt_snap
,
2618 tmpl_prop_name
, pg
) != 0) {
2619 if (!ismember(scf_error(), errors_server
)) {
2620 switch (scf_error()) {
2621 case SCF_ERROR_NOT_FOUND
:
2622 case SCF_ERROR_INVALID_ARGUMENT
:
2625 case SCF_ERROR_NOT_SET
:
2626 case SCF_ERROR_HANDLE_MISMATCH
:
2634 * We've only found a template property group if the type
2637 if ((pg_type
= _scf_get_pg_type(pg
)) != NULL
&&
2638 strcmp(pg_type
, SCF_GROUP_TEMPLATE_PROP_PATTERN
) == 0)
2641 (void) scf_set_error(SCF_ERROR_TYPE_MISMATCH
);
2649 free(tmpl_prop_name
);
2653 prop_tmpl
->prt_h
= scf_pg_handle(t
->pt_pg
);
2654 prop_tmpl
->prt_t
= t
;
2655 prop_tmpl
->prt_pg
= pg
;
2656 prop_tmpl
->prt_pg_name
= tmpl_prop_name
;
2657 prop_tmpl
->prt_populated
= 1;
2663 * scf_prop_tmpl_t *scf_tmpl_prop_create(scf_handle_t *);
2665 * Returns NULL on failure, sets scf_error() to _INVALID_ARGUMENT, or
2669 scf_tmpl_prop_create(scf_handle_t
*handle
)
2671 scf_prop_tmpl_t
*pt
;
2673 if (handle
== NULL
) {
2674 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2677 pt
= calloc(1, sizeof (scf_prop_tmpl_t
));
2679 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2687 * int scf_tmpl_iter_props()
2689 * Iterates over all property templates defined in the specified property
2690 * group template. The iterator state is stored on the property template
2691 * data structure, and the data structure should be allocated with
2692 * scf_tmpl_prop_create(). To continue the iteration, the previously
2693 * returned structure should be passed in as an argument to this function.
2694 * flags can include SCF_PROP_TMPL_FLAG_REQUIRED. The function returns
2695 * 1 when a result was found, and 0 when the iteration is complete.
2697 * Returns -1 on failure, and sets scf_error():
2698 * SCF_ERROR_BACKEND_ACCESS
2699 * SCF_ERROR_CONNECTION_BROKEN
2701 * SCF_ERROR_HANDLE_DESTROYED
2702 * SCF_ERROR_INTERNAL
2703 * SCF_ERROR_INVALID_ARGUMENT
2704 * SCF_ERROR_NO_MEMORY
2705 * SCF_ERROR_NO_RESOURCES
2706 * SCF_ERROR_NOT_BOUND
2707 * SCF_ERROR_PERMISSION_DENIED
2708 * SCF_ERROR_TEMPLATE_INVALID
2709 * Template data is invalid. One of the property templates in this
2710 * pg_tmpl is malformed.
2713 scf_tmpl_iter_props(scf_pg_tmpl_t
*t
, scf_prop_tmpl_t
*pt
, int flags
)
2715 scf_prop_tmpl_t
*prop_tmpl
;
2717 char *pg_name
= NULL
;
2720 ssize_t size
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
2723 scf_propertygroup_t
*pg
= NULL
;
2724 scf_iter_t
*iter
= NULL
;
2727 if (t
== NULL
|| pt
== NULL
) {
2728 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
2732 assert(t
->pt_inst
== NULL
|| t
->pt_svc
== NULL
);
2733 assert(t
->pt_inst
!= NULL
|| t
->pt_svc
!= NULL
);
2735 if ((pg_name
= malloc(size
)) == NULL
) {
2736 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
2740 if (pt
->prt_populated
== 0) {
2741 if ((h
= scf_pg_handle(t
->pt_pg
)) == NULL
)
2742 goto fail_non_populated
;
2744 if ((pg
= scf_pg_create(h
)) == NULL
||
2745 (iter
= scf_iter_create(h
)) == NULL
)
2746 goto fail_non_populated
;
2748 if (t
->pt_inst
!= NULL
)
2749 err
= scf_iter_instance_pgs_typed_composed(iter
,
2750 t
->pt_inst
, t
->pt_snap
,
2751 SCF_GROUP_TEMPLATE_PROP_PATTERN
);
2752 else if (t
->pt_svc
!= NULL
)
2753 err
= scf_iter_service_pgs_typed(iter
, t
->pt_svc
,
2754 SCF_GROUP_TEMPLATE_PROP_PATTERN
);
2757 if (ismember(scf_error(), errors_server
)) {
2758 goto fail_non_populated
;
2759 } else switch (scf_error()) {
2760 case SCF_ERROR_INVALID_ARGUMENT
:
2761 goto fail_non_populated
;
2763 case SCF_ERROR_NOT_SET
:
2764 case SCF_ERROR_HANDLE_MISMATCH
:
2772 prop_tmpl
->prt_t
= t
;
2773 prop_tmpl
->prt_populated
= 1;
2774 prop_tmpl
->prt_pg
= pg
;
2775 prop_tmpl
->prt_iter
= iter
;
2780 while ((err
= scf_iter_next_pg(prop_tmpl
->prt_iter
,
2781 prop_tmpl
->prt_pg
)) > 0) {
2783 * Check if the name matches the appropriate property
2784 * group template name.
2786 pg_pat
= _scf_read_single_astring_from_pg(prop_tmpl
->prt_pg
,
2787 SCF_PROPERTY_TM_PG_PATTERN
);
2788 if (pg_pat
== NULL
) {
2789 if (ismember(scf_error(), errors_server
)) {
2792 } else switch (scf_error()) {
2793 case SCF_ERROR_NOT_FOUND
:
2796 case SCF_ERROR_CONSTRAINT_VIOLATED
:
2797 case SCF_ERROR_TYPE_MISMATCH
:
2798 (void) scf_set_error(
2799 SCF_ERROR_TEMPLATE_INVALID
);
2803 case SCF_ERROR_INVALID_ARGUMENT
:
2804 case SCF_ERROR_NOT_SET
:
2810 if ((ret
= scf_pg_get_name(t
->pt_pg
, pg_name
, size
)) <= 0) {
2815 if (ismember(scf_error(), errors_server
)) {
2823 if (strcmp(pg_pat
, pg_name
) != 0) {
2830 * If walking only required properties, check if
2831 * the retrieved property is required.
2833 if (flags
& SCF_PROP_TMPL_FLAG_REQUIRED
) {
2834 if (scf_tmpl_prop_required(prop_tmpl
, &required
) == 0) {
2847 if (ismember(scf_error(), errors_server
)) {
2854 } else if (err
== 0) {
2855 scf_iter_destroy(prop_tmpl
->prt_iter
);
2856 prop_tmpl
->prt_iter
= NULL
;
2857 prop_tmpl
->prt_populated
= 0;
2866 scf_iter_destroy(iter
);
2871 scf_tmpl_prop_destroy(scf_prop_tmpl_t
*t
)
2876 scf_pg_destroy(t
->prt_pg
);
2877 free(t
->prt_pg_name
);
2883 scf_tmpl_prop_reset(scf_prop_tmpl_t
*t
)
2885 scf_pg_destroy(t
->prt_pg
);
2888 free(t
->prt_pg_name
);
2889 t
->prt_pg_name
= NULL
;
2894 t
->prt_populated
= 0;
2900 * Returns -1 on failure. Sets scf_error():
2901 * SCF_ERROR_BACKEND_ACCESS
2902 * SCF_ERROR_CONNECTION_BROKEN
2904 * SCF_ERROR_HANDLE_DESTROYED
2905 * SCF_ERROR_INTERNAL
2906 * SCF_ERROR_NO_MEMORY
2907 * SCF_ERROR_NO_RESOURCES
2908 * SCF_ERROR_NOT_BOUND
2909 * SCF_ERROR_PERMISSION_DENIED
2910 * SCF_ERROR_TEMPLATE_INVALID
2911 * The name of the template property group (the pname property) has
2912 * an improper repository format and is not type astring or has
2913 * more than one value.
2916 scf_tmpl_pg_name(const scf_pg_tmpl_t
*t
, char **out
)
2918 return (_scf_tmpl_prop_value(t
->pt_pg
, SCF_PROPERTY_TM_NAME
, out
));
2922 * returns an allocated string that must be freed
2924 * Returns NULL on failure, sets scf_error() to:
2925 * SCF_ERROR_BACKEND_ACCESS
2926 * SCF_ERROR_CONNECTION_BROKEN
2928 * SCF_ERROR_HANDLE_DESTROYED
2929 * SCF_ERROR_INTERNAL
2930 * SCF_ERROR_INVALID_ARGUMENT
2931 * name not a valid property name
2932 * name and locale are too long to make a property name
2933 * SCF_ERROR_NO_MEMORY
2934 * SCF_ERROR_NO_RESOURCES
2935 * SCF_ERROR_NOT_BOUND
2936 * SCF_ERROR_NOT_FOUND
2937 * Property doesn't exist or exists and has no value.
2938 * SCF_ERROR_PERMISSION_DENIED
2939 * SCF_ERROR_TEMPLATE_INVALID
2942 _read_localized_astring_from_pg(scf_propertygroup_t
*pg
, const char *name
,
2948 str
= _add_locale_to_name(name
, locale
);
2951 lname_prop
= _scf_read_single_astring_from_pg(pg
, str
);
2952 if (lname_prop
== NULL
) {
2954 if (scf_error() != SCF_ERROR_NOT_FOUND
)
2956 str
= _add_locale_to_name(name
, "C");
2959 lname_prop
= _scf_read_single_astring_from_pg(pg
, str
);
2962 if (lname_prop
== NULL
) {
2963 if (scf_error() == SCF_ERROR_TYPE_MISMATCH
||
2964 scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
)
2965 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
2967 return (lname_prop
);
2971 * returns an allocated string that must be freed
2973 * Returns -1 on failure, sets scf_error() to:
2974 * SCF_ERROR_BACKEND_ACCESS
2975 * SCF_ERROR_CONNECTION_BROKEN
2977 * SCF_ERROR_HANDLE_DESTROYED
2978 * SCF_ERROR_INTERNAL
2979 * SCF_ERROR_INVALID_ARGUMENT
2980 * locale is too long to make a valid property name
2981 * SCF_ERROR_NO_MEMORY
2982 * SCF_ERROR_NO_RESOURCES
2983 * SCF_ERROR_NOT_BOUND
2984 * SCF_ERROR_NOT_FOUND
2985 * Property doesn't exist or exists and has no value.
2986 * SCF_ERROR_PERMISSION_DENIED
2987 * SCF_ERROR_TEMPLATE_INVALID
2990 scf_tmpl_pg_common_name(const scf_pg_tmpl_t
*t
, const char *locale
, char **out
)
2992 assert(out
!= NULL
);
2993 if ((*out
= _read_localized_astring_from_pg(t
->pt_pg
,
2994 SCF_PROPERTY_TM_COMMON_NAME_PREFIX
, locale
)) == NULL
)
2997 return (strlen(*out
));
3001 * returns an allocated string that must be freed
3003 * Returns -1 on failure, sets scf_error() to:
3004 * SCF_ERROR_BACKEND_ACCESS
3005 * SCF_ERROR_CONNECTION_BROKEN
3007 * SCF_ERROR_HANDLE_DESTROYED
3008 * SCF_ERROR_INTERNAL
3009 * SCF_ERROR_INVALID_ARGUMENT
3010 * locale is too long to make a valid property name
3011 * SCF_ERROR_NO_MEMORY
3012 * SCF_ERROR_NO_RESOURCES
3013 * SCF_ERROR_NOT_BOUND
3014 * SCF_ERROR_NOT_FOUND
3015 * Property doesn't exist or exists and has no value.
3016 * SCF_ERROR_PERMISSION_DENIED
3017 * SCF_ERROR_TEMPLATE_INVALID
3020 scf_tmpl_pg_description(const scf_pg_tmpl_t
*t
, const char *locale
, char **out
)
3022 assert(out
!= NULL
);
3023 if ((*out
= _read_localized_astring_from_pg(t
->pt_pg
,
3024 SCF_PROPERTY_TM_DESCRIPTION_PREFIX
, locale
)) == NULL
)
3027 return (strlen(*out
));
3031 * Returns -1 on failure. Sets scf_error():
3032 * SCF_ERROR_BACKEND_ACCESS
3033 * SCF_ERROR_CONNECTION_BROKEN
3035 * SCF_ERROR_HANDLE_DESTROYED
3036 * SCF_ERROR_INTERNAL
3037 * SCF_ERROR_NO_MEMORY
3038 * SCF_ERROR_NO_RESOURCES
3039 * SCF_ERROR_NOT_BOUND
3040 * SCF_ERROR_NOT_FOUND
3041 * 'type' property doesn't exist or exists and has no value.
3042 * SCF_ERROR_PERMISSION_DENIED
3043 * SCF_ERROR_TEMPLATE_INVALID
3044 * 'type' property is not SCF_TYPE_ASTRING or has more than one value.
3047 scf_tmpl_pg_type(const scf_pg_tmpl_t
*t
, char **out
)
3049 return (_scf_tmpl_prop_value(t
->pt_pg
, SCF_PROPERTY_TM_TYPE
, out
));
3053 * Returns -1 on failure, sets scf_error() to:
3054 * SCF_ERROR_BACKEND_ACCESS
3055 * SCF_ERROR_CONNECTION_BROKEN
3057 * SCF_ERROR_HANDLE_DESTROYED
3058 * SCF_ERROR_INTERNAL
3059 * SCF_ERROR_NO_MEMORY
3060 * SCF_ERROR_NO_RESOURCES
3061 * SCF_ERROR_NOT_BOUND
3062 * SCF_ERROR_PERMISSION_DENIED
3063 * SCF_ERROR_TEMPLATE_INVALID
3064 * required property is not SCF_TYPE_BOOLEAN or has more than one value.
3067 scf_tmpl_pg_required(const scf_pg_tmpl_t
*t
, uint8_t *out
)
3070 if (_read_single_boolean_from_pg(t
->pt_pg
, SCF_PROPERTY_TM_REQUIRED
,
3072 if (ismember(scf_error(), errors_server
)) {
3074 } else switch (scf_error()) {
3075 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3076 case SCF_ERROR_TYPE_MISMATCH
:
3077 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3080 case SCF_ERROR_NOT_FOUND
:
3084 case SCF_ERROR_INVALID_ARGUMENT
:
3095 * Returns -1 on failure. Sets scf_error():
3096 * SCF_ERROR_BACKEND_ACCESS
3097 * SCF_ERROR_CONNECTION_BROKEN
3099 * SCF_ERROR_HANDLE_DESTROYED
3100 * SCF_ERROR_INTERNAL
3101 * SCF_ERROR_NO_MEMORY
3102 * SCF_ERROR_NO_RESOURCES
3103 * SCF_ERROR_NOT_BOUND
3104 * SCF_ERROR_PERMISSION_DENIED
3105 * SCF_ERROR_TEMPLATE_INVALID
3106 * target property is not SCF_TYPE_ASTRING or has more than one value.
3109 scf_tmpl_pg_target(const scf_pg_tmpl_t
*t
, char **out
)
3111 *out
= _scf_read_single_astring_from_pg(t
->pt_pg
,
3112 SCF_PROPERTY_TM_TARGET
);
3115 if (ismember(scf_error(), errors_server
)) {
3117 } else switch (scf_error()) {
3118 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3119 case SCF_ERROR_NOT_FOUND
:
3120 case SCF_ERROR_TYPE_MISMATCH
:
3121 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3124 case SCF_ERROR_INVALID_ARGUMENT
:
3125 case SCF_ERROR_NOT_SET
:
3132 return (strlen(*out
));
3136 * Returns -1 on failure. Sets scf_error():
3137 * SCF_ERROR_BACKEND_ACCESS
3138 * SCF_ERROR_CONNECTION_BROKEN
3140 * SCF_ERROR_HANDLE_DESTROYED
3141 * SCF_ERROR_INTERNAL
3142 * SCF_ERROR_NO_MEMORY
3143 * SCF_ERROR_NO_RESOURCES
3144 * SCF_ERROR_NOT_BOUND
3145 * SCF_ERROR_PERMISSION_DENIED
3146 * SCF_ERROR_TEMPLATE_INVALID
3149 scf_tmpl_prop_name(const scf_prop_tmpl_t
*t
, char **out
)
3151 *out
= _scf_read_single_astring_from_pg(t
->prt_pg
,
3152 SCF_PROPERTY_TM_NAME
);
3154 if (*out
!= NULL
&& *out
[0] == '\0') {
3157 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3160 if (ismember(scf_error(), errors_server
)) {
3162 } else switch (scf_error()) {
3163 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3164 case SCF_ERROR_NOT_FOUND
:
3165 case SCF_ERROR_TEMPLATE_INVALID
:
3166 case SCF_ERROR_TYPE_MISMATCH
:
3167 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3170 case SCF_ERROR_INVALID_ARGUMENT
:
3171 case SCF_ERROR_NOT_SET
:
3178 return (strlen(*out
));
3182 * Returns -1 on failure. Sets scf_error():
3183 * SCF_ERROR_BACKEND_ACCESS
3184 * SCF_ERROR_CONNECTION_BROKEN
3186 * SCF_ERROR_HANDLE_DESTROYED
3187 * SCF_ERROR_INTERNAL
3188 * SCF_ERROR_NO_MEMORY
3189 * SCF_ERROR_NO_RESOURCES
3190 * SCF_ERROR_NOT_BOUND
3191 * SCF_ERROR_NOT_FOUND
3192 * 'type' property doesn't exist or exists and has no value.
3193 * SCF_ERROR_PERMISSION_DENIED
3194 * SCF_ERROR_TEMPLATE_INVALID
3195 * 'type' property is not SCF_TYPE_ASTRING, has more than one value,
3196 * is SCF_TYPE_INVALID, or is the empty string.
3199 scf_tmpl_prop_type(const scf_prop_tmpl_t
*t
, scf_type_t
*out
)
3203 type
= _scf_read_single_astring_from_pg(t
->prt_pg
,
3204 SCF_PROPERTY_TM_TYPE
);
3205 if (type
!= NULL
&& type
[0] == '\0') {
3207 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3211 if (ismember(scf_error(), errors_server
)) {
3213 } else switch (scf_error()) {
3214 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3215 case SCF_ERROR_TYPE_MISMATCH
:
3216 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3219 case SCF_ERROR_NOT_FOUND
:
3222 case SCF_ERROR_INVALID_ARGUMENT
:
3223 case SCF_ERROR_NOT_SET
:
3230 *out
= scf_string_to_type(type
);
3233 if (*out
== SCF_TYPE_INVALID
) {
3234 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3242 * Returns -1 on failure, sets scf_error() to:
3243 * SCF_ERROR_BACKEND_ACCESS
3244 * SCF_ERROR_CONNECTION_BROKEN
3246 * Property group which represents t was deleted.
3247 * SCF_ERROR_HANDLE_DESTROYED
3248 * SCF_ERROR_INTERNAL
3249 * SCF_ERROR_NO_MEMORY
3250 * SCF_ERROR_NO_RESOURCES
3251 * SCF_ERROR_NOT_BOUND
3252 * SCF_ERROR_PERMISSION_DENIED
3253 * SCF_ERROR_TEMPLATE_INVALID
3254 * required property is not SCF_TYPE_ASTRING has more than one value.
3257 scf_tmpl_prop_required(const scf_prop_tmpl_t
*t
, uint8_t *out
)
3259 if (_read_single_boolean_from_pg(t
->prt_pg
, SCF_PROPERTY_TM_REQUIRED
,
3261 if (ismember(scf_error(), errors_server
)) {
3263 } else switch (scf_error()) {
3264 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3265 case SCF_ERROR_TYPE_MISMATCH
:
3266 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3269 case SCF_ERROR_NOT_FOUND
:
3273 case SCF_ERROR_INVALID_ARGUMENT
:
3274 case SCF_ERROR_NOT_SET
:
3285 * Returns -1 on failure. Sets scf_error():
3286 * SCF_ERROR_BACKEND_ACCESS
3287 * SCF_ERROR_CONNECTION_BROKEN
3289 * SCF_ERROR_HANDLE_DESTROYED
3290 * SCF_ERROR_INTERNAL
3291 * SCF_ERROR_NO_MEMORY
3292 * SCF_ERROR_NO_RESOURCES
3293 * SCF_ERROR_NOT_BOUND
3294 * SCF_ERROR_NOT_FOUND
3295 * Property doesn't exist or exists and has no value.
3296 * SCF_ERROR_INVALID_ARGUMENT
3297 * locale is too long to make a property name
3298 * SCF_ERROR_PERMISSION_DENIED
3299 * SCF_ERROR_TEMPLATE_INVALID
3300 * common_name property is not SCF_TYPE_ASTRING has more than one value.
3303 scf_tmpl_prop_common_name(const scf_prop_tmpl_t
*t
, const char *locale
,
3306 assert(out
!= NULL
);
3307 if ((*out
= _read_localized_astring_from_pg(t
->prt_pg
,
3308 SCF_PROPERTY_TM_COMMON_NAME_PREFIX
, locale
)) == NULL
)
3311 return (strlen(*out
));
3315 * Returns -1 on failure. Sets scf_error():
3316 * SCF_ERROR_BACKEND_ACCESS
3317 * SCF_ERROR_CONNECTION_BROKEN
3319 * SCF_ERROR_HANDLE_DESTROYED
3320 * SCF_ERROR_INTERNAL
3321 * SCF_ERROR_NO_MEMORY
3322 * SCF_ERROR_NO_RESOURCES
3323 * SCF_ERROR_NOT_BOUND
3324 * SCF_ERROR_NOT_FOUND
3325 * Property doesn't exist or exists and has no value.
3326 * SCF_ERROR_INVALID_ARGUMENT
3327 * locale is too long to make a property name
3328 * SCF_ERROR_PERMISSION_DENIED
3329 * SCF_ERROR_TEMPLATE_INVALID
3330 * description property is not SCF_TYPE_ASTRING has more than one value.
3333 scf_tmpl_prop_description(const scf_prop_tmpl_t
*t
, const char *locale
,
3336 assert(out
!= NULL
);
3337 if ((*out
= _read_localized_astring_from_pg(t
->prt_pg
,
3338 SCF_PROPERTY_TM_DESCRIPTION_PREFIX
, locale
)) == NULL
)
3341 return (strlen(*out
));
3345 * Returns -1 on failure. Sets scf_error():
3346 * SCF_ERROR_BACKEND_ACCESS
3347 * SCF_ERROR_CONNECTION_BROKEN
3349 * SCF_ERROR_HANDLE_DESTROYED
3350 * SCF_ERROR_INTERNAL
3351 * SCF_ERROR_NO_MEMORY
3352 * SCF_ERROR_NO_RESOURCES
3353 * SCF_ERROR_NOT_BOUND
3354 * SCF_ERROR_NOT_FOUND
3355 * Property doesn't exist or exists and has no value.
3356 * SCF_ERROR_INVALID_ARGUMENT
3357 * locale is too long to make a property name
3358 * SCF_ERROR_PERMISSION_DENIED
3359 * SCF_ERROR_TEMPLATE_INVALID
3360 * units property is not SCF_TYPE_ASTRING has more than one value.
3363 scf_tmpl_prop_units(const scf_prop_tmpl_t
*t
, const char *locale
, char **out
)
3365 assert(out
!= NULL
);
3366 if ((*out
= _read_localized_astring_from_pg(t
->prt_pg
,
3367 SCF_PROPERTY_TM_UNITS_PREFIX
, locale
)) == NULL
)
3370 return (strlen(*out
));
3374 * Returns -1 on failure. Sets scf_error():
3375 * SCF_ERROR_BACKEND_ACCESS
3376 * SCF_ERROR_CONNECTION_BROKEN
3378 * SCF_ERROR_HANDLE_DESTROYED
3379 * SCF_ERROR_INTERNAL
3380 * SCF_ERROR_NO_MEMORY
3381 * SCF_ERROR_NO_RESOURCES
3382 * SCF_ERROR_NOT_BOUND
3383 * SCF_ERROR_PERMISSION_DENIED
3384 * SCF_ERROR_TEMPLATE_INVALID
3385 * visibility property is not SCF_TYPE_ASTRING has more than one value.
3388 scf_tmpl_prop_visibility(const scf_prop_tmpl_t
*t
, uint8_t *out
)
3392 visibility
= _scf_read_single_astring_from_pg(t
->prt_pg
,
3393 SCF_PROPERTY_TM_VISIBILITY
);
3394 if (visibility
== NULL
) {
3395 if (ismember(scf_error(), errors_server
)) {
3397 } else switch (scf_error()) {
3398 /* prop doesn't exist we take the default value */
3399 case SCF_ERROR_NOT_FOUND
:
3400 *out
= SCF_TMPL_VISIBILITY_READWRITE
;
3403 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3404 case SCF_ERROR_TYPE_MISMATCH
:
3405 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3408 case SCF_ERROR_INVALID_ARGUMENT
:
3409 case SCF_ERROR_NOT_SET
:
3414 } else if (strcmp(visibility
, SCF_TM_VISIBILITY_READWRITE
) == 0) {
3415 *out
= SCF_TMPL_VISIBILITY_READWRITE
;
3416 } else if (strcmp(visibility
, SCF_TM_VISIBILITY_HIDDEN
) == 0) {
3417 *out
= SCF_TMPL_VISIBILITY_HIDDEN
;
3418 } else if (strcmp(visibility
, SCF_TM_VISIBILITY_READONLY
) == 0) {
3419 *out
= SCF_TMPL_VISIBILITY_READONLY
;
3422 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3431 * Return an allocated string containing the value that must be freed
3434 * On error set scf_error() _NO_MEMORY, or _NOT_SET (val has not been set
3438 _scf_value_get_as_string(scf_value_t
*val
)
3440 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
3441 char *buf
= malloc(sz
);
3444 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3445 } else if (scf_value_get_as_string(val
, buf
, sz
) == -1) {
3454 * Returns -1 on failure, sets scf_error() to:
3455 * SCF_ERROR_BACKEND_ACCESS
3456 * SCF_ERROR_CONNECTION_BROKEN
3458 * SCF_ERROR_HANDLE_DESTROYED
3459 * SCF_ERROR_INTERNAL
3460 * SCF_ERROR_NO_MEMORY
3461 * SCF_ERROR_NO_RESOURCES
3462 * SCF_ERROR_NOT_BOUND
3463 * SCF_ERROR_NOT_FOUND
3464 * SCF_ERROR_PERMISSION_DENIED
3465 * SCF_ERROR_TEMPLATE_INVALID
3468 scf_tmpl_prop_cardinality(const scf_prop_tmpl_t
*t
, uint64_t *min
,
3471 scf_value_t
*val_min
= NULL
;
3472 scf_value_t
*val_max
= NULL
;
3475 if (_read_single_value_from_pg(t
->prt_pg
,
3476 SCF_PROPERTY_TM_CARDINALITY_MIN
, &val_min
) == 0) {
3477 if (scf_value_get_count(val_min
, min
) < 0)
3480 if (scf_error() == SCF_ERROR_NOT_FOUND
)
3486 if (_read_single_value_from_pg(t
->prt_pg
,
3487 SCF_PROPERTY_TM_CARDINALITY_MAX
, &val_max
) == 0) {
3488 if (scf_value_get_count(val_max
, max
) < 0)
3491 if (scf_error() == SCF_ERROR_NOT_FOUND
)
3499 if (ismember(scf_error(), errors_server
)) {
3501 } else switch (scf_error()) {
3502 case SCF_ERROR_TYPE_MISMATCH
:
3503 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3504 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3507 case SCF_ERROR_NOT_FOUND
:
3508 case SCF_ERROR_TEMPLATE_INVALID
:
3512 case SCF_ERROR_NOT_SET
:
3513 case SCF_ERROR_INVALID_ARGUMENT
:
3520 scf_value_destroy(val_min
);
3521 scf_value_destroy(val_max
);
3527 * Returns -1 on failure. Sets scf_error():
3528 * SCF_ERROR_BACKEND_ACCESS
3529 * SCF_ERROR_CONNECTION_BROKEN
3531 * SCF_ERROR_HANDLE_DESTROYED
3532 * SCF_ERROR_INTERNAL
3533 * SCF_ERROR_NO_MEMORY
3534 * SCF_ERROR_NO_RESOURCES
3535 * SCF_ERROR_NOT_BOUND
3536 * SCF_ERROR_NOT_FOUND
3537 * Property doesn't exist or exists and has no value.
3538 * SCF_ERROR_PERMISSION_DENIED
3539 * SCF_ERROR_TEMPLATE_INVALID
3542 scf_tmpl_prop_internal_seps(const scf_prop_tmpl_t
*t
, scf_values_t
*vals
)
3544 if (_read_astrings_values(t
->prt_pg
,
3545 SCF_PROPERTY_INTERNAL_SEPARATORS
, vals
) == NULL
) {
3546 if (ismember(scf_error(), errors_server
)) {
3548 } else switch (scf_error()) {
3549 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3550 case SCF_ERROR_TYPE_MISMATCH
:
3551 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3554 case SCF_ERROR_NOT_FOUND
:
3557 case SCF_ERROR_INVALID_ARGUMENT
:
3558 case SCF_ERROR_NOT_SET
:
3563 } else if (vals
->value_count
== 0) {
3564 /* property has no value */
3565 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3566 scf_values_destroy(vals
);
3574 * Returns -1 on failure. Sets scf_error():
3575 * SCF_ERROR_BACKEND_ACCESS
3576 * SCF_ERROR_CONNECTION_BROKEN
3578 * SCF_ERROR_HANDLE_DESTROYED
3579 * SCF_ERROR_INTERNAL
3580 * SCF_ERROR_NO_MEMORY
3581 * SCF_ERROR_NO_RESOURCES
3582 * SCF_ERROR_NOT_BOUND
3583 * SCF_ERROR_NOT_FOUND
3584 * Property doesn't exist or exists and has no value.
3585 * SCF_ERROR_PERMISSION_DENIED
3586 * SCF_ERROR_TEMPLATE_INVALID
3589 scf_tmpl_value_name_constraints(const scf_prop_tmpl_t
*t
,
3594 ret
= _read_astrings_values(t
->prt_pg
,
3595 SCF_PROPERTY_TM_CONSTRAINT_NAME
, vals
);
3598 if (ismember(scf_error(), errors_server
)) {
3600 } else switch (scf_error()) {
3601 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3602 case SCF_ERROR_TYPE_MISMATCH
:
3603 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3606 case SCF_ERROR_NOT_FOUND
:
3609 case SCF_ERROR_INVALID_ARGUMENT
:
3610 case SCF_ERROR_NOT_SET
:
3615 } else if (vals
->value_count
== 0) {
3616 /* property has no value */
3617 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3618 scf_values_destroy(vals
);
3626 * Returns NULL on failure. Sets scf_error():
3627 * Caller is responsible for freeing returned pointer after use.
3628 * SCF_ERROR_CONSTRAINT_VIOLATED
3629 * More tokens than the array size supplied.
3630 * SCF_ERROR_NO_MEMORY
3633 _separate_by_separator(char *string
, const char *sep
, char **array
, int size
)
3639 assert(array
!= NULL
);
3640 assert(string
!= NULL
);
3641 assert(sep
!= NULL
);
3644 str
= strdup(string
);
3646 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3650 if ((array
[n
] = strtok_r(str
, sep
, &lasts
)) == NULL
) {
3656 while ((token
= strtok_r(NULL
, sep
, &lasts
)) != NULL
) {
3670 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3675 * check if name is among values of CHOICES_INCLUDE_VALUES
3676 * return 0 if name is present, 1 name is not present, -1 on failure
3677 * SCF_ERROR_BACKEND_ACCESS
3678 * SCF_ERROR_CONNECTION_BROKEN
3680 * SCF_ERROR_HANDLE_DESTROYED
3681 * SCF_ERROR_INTERNAL
3682 * SCF_ERROR_NO_MEMORY
3683 * SCF_ERROR_NO_RESOURCES
3684 * SCF_ERROR_NOT_BOUND
3685 * SCF_ERROR_PERMISSION_DENIED
3686 * SCF_ERROR_TEMPLATE_INVALID
3689 _check_choices_include_values(scf_propertygroup_t
*pg
, const char *name
)
3695 if ((ret
= _read_astrings_values(pg
,
3696 SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES
, &vals
)) == NULL
) {
3697 if (ismember(scf_error(), errors_server
)) {
3699 } else switch (scf_error()) {
3700 case SCF_ERROR_NOT_FOUND
:
3703 case SCF_ERROR_TYPE_MISMATCH
:
3704 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3707 case SCF_ERROR_INVALID_ARGUMENT
:
3708 case SCF_ERROR_NOT_SET
:
3715 for (n
= 0; n
< vals
.value_count
; ++n
) {
3716 if (strcmp(name
, ret
[n
]) == 0) {
3721 scf_values_destroy(&vals
);
3726 scf_count_ranges_destroy(scf_count_ranges_t
*ranges
)
3731 ranges
->scr_num_ranges
= 0;
3732 free(ranges
->scr_min
);
3733 free(ranges
->scr_max
);
3734 ranges
->scr_min
= NULL
;
3735 ranges
->scr_max
= NULL
;
3739 scf_int_ranges_destroy(scf_int_ranges_t
*ranges
)
3744 ranges
->sir_num_ranges
= 0;
3745 free(ranges
->sir_min
);
3746 free(ranges
->sir_max
);
3747 ranges
->sir_min
= NULL
;
3748 ranges
->sir_max
= NULL
;
3752 * Returns -1 on failure. Sets scf_error():
3753 * SCF_ERROR_BACKEND_ACCESS
3754 * SCF_ERROR_CONNECTION_BROKEN
3755 * SCF_ERROR_CONSTRAINT_VIOLATED
3757 * SCF_ERROR_HANDLE_DESTROYED
3758 * SCF_ERROR_INTERNAL
3759 * SCF_ERROR_NO_MEMORY
3760 * SCF_ERROR_NO_RESOURCES
3761 * SCF_ERROR_NOT_BOUND
3762 * SCF_ERROR_NOT_FOUND
3763 * Property doesn't exist or exists and has no value.
3764 * SCF_ERROR_PERMISSION_DENIED
3765 * SCF_ERROR_TEMPLATE_INVALID
3768 _scf_tmpl_get_count_ranges(const scf_prop_tmpl_t
*t
, const char *prop
,
3769 scf_count_ranges_t
*ranges
)
3777 uint64_t *min
= NULL
;
3778 uint64_t *max
= NULL
;
3780 assert(ranges
!= NULL
);
3781 if ((ret
= _read_astrings_values(t
->prt_pg
, prop
, &vals
)) == NULL
)
3783 if (vals
.value_count
== 0) {
3784 /* range values are empty */
3785 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3789 min
= malloc(vals
.value_count
* sizeof (uint64_t));
3790 max
= malloc(vals
.value_count
* sizeof (uint64_t));
3791 if (min
== NULL
|| max
== NULL
) {
3792 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3795 for (i
= 0; i
< vals
.value_count
; ++i
) {
3796 /* min and max should be separated by a "," */
3797 if ((str
= _separate_by_separator(ret
[i
], ",", one_range
,
3801 min
[i
] = strtoull(one_range
[0], &endptr
, 10);
3802 if (errno
!= 0 || endptr
== one_range
[0] || *endptr
) {
3803 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3807 max
[i
] = strtoull(one_range
[1], &endptr
, 10);
3808 if (errno
!= 0 || endptr
== one_range
[1] || *endptr
) {
3809 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3812 if (min
[i
] > max
[i
]) {
3813 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3819 ranges
->scr_num_ranges
= vals
.value_count
;
3820 ranges
->scr_min
= min
;
3821 ranges
->scr_max
= max
;
3822 scf_values_destroy(&vals
);
3828 scf_values_destroy(&vals
);
3830 if (ismember(scf_error(), errors_server
)) {
3832 } else switch (scf_error()) {
3833 case SCF_ERROR_TYPE_MISMATCH
:
3834 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3837 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3838 case SCF_ERROR_NOT_FOUND
:
3841 case SCF_ERROR_INVALID_ARGUMENT
:
3842 case SCF_ERROR_NOT_SET
:
3851 * Returns -1 on failure. Sets scf_error():
3852 * SCF_ERROR_BACKEND_ACCESS
3853 * SCF_ERROR_CONNECTION_BROKEN
3854 * SCF_ERROR_CONSTRAINT_VIOLATED
3856 * SCF_ERROR_HANDLE_DESTROYED
3857 * SCF_ERROR_INTERNAL
3858 * SCF_ERROR_NO_MEMORY
3859 * SCF_ERROR_NO_RESOURCES
3860 * SCF_ERROR_NOT_BOUND
3861 * SCF_ERROR_NOT_FOUND
3862 * Property doesn't exist or exists and has no value.
3863 * SCF_ERROR_PERMISSION_DENIED
3864 * SCF_ERROR_TEMPLATE_INVALID
3867 _scf_tmpl_get_int_ranges(const scf_prop_tmpl_t
*t
, const char *prop
,
3868 scf_int_ranges_t
*ranges
)
3876 int64_t *min
= NULL
;
3877 int64_t *max
= NULL
;
3879 assert(ranges
!= NULL
);
3880 if ((ret
= _read_astrings_values(t
->prt_pg
, prop
, &vals
)) == NULL
)
3882 if (vals
.value_count
== 0) {
3883 /* range values are empty */
3884 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
3888 min
= malloc(vals
.value_count
* sizeof (int64_t));
3889 max
= malloc(vals
.value_count
* sizeof (int64_t));
3890 if (min
== NULL
|| max
== NULL
) {
3891 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
3894 while (n
< vals
.value_count
) {
3895 /* min and max should be separated by a "," */
3896 if ((str
= _separate_by_separator(ret
[n
], ",", one_range
, 2))
3900 min
[n
] = strtoll(one_range
[0], &endptr
, 10);
3901 if (errno
!= 0 || endptr
== one_range
[0] || *endptr
) {
3902 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3906 max
[n
] = strtoll(one_range
[1], &endptr
, 10);
3907 if (errno
!= 0 || endptr
== one_range
[1] || *endptr
) {
3908 (void) scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED
);
3911 if (min
[n
] > max
[n
]) {
3912 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3919 ranges
->sir_num_ranges
= vals
.value_count
;
3920 ranges
->sir_min
= min
;
3921 ranges
->sir_max
= max
;
3922 scf_values_destroy(&vals
);
3928 scf_values_destroy(&vals
);
3930 if (ismember(scf_error(), errors_server
)) {
3932 } else switch (scf_error()) {
3933 case SCF_ERROR_TYPE_MISMATCH
:
3934 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
3937 case SCF_ERROR_CONSTRAINT_VIOLATED
:
3938 case SCF_ERROR_NOT_FOUND
:
3939 case SCF_ERROR_TEMPLATE_INVALID
:
3942 case SCF_ERROR_INVALID_ARGUMENT
:
3943 case SCF_ERROR_NOT_SET
:
3952 * Returns -1 on failure. Sets scf_error():
3953 * SCF_ERROR_BACKEND_ACCESS
3954 * SCF_ERROR_CONNECTION_BROKEN
3955 * SCF_ERROR_CONSTRAINT_VIOLATED
3957 * SCF_ERROR_HANDLE_DESTROYED
3958 * SCF_ERROR_INTERNAL
3959 * SCF_ERROR_NO_MEMORY
3960 * SCF_ERROR_NO_RESOURCES
3961 * SCF_ERROR_NOT_BOUND
3962 * SCF_ERROR_NOT_FOUND
3963 * Property doesn't exist or exists and has no value.
3964 * SCF_ERROR_PERMISSION_DENIED
3965 * SCF_ERROR_TEMPLATE_INVALID
3968 scf_tmpl_value_count_range_constraints(const scf_prop_tmpl_t
*t
,
3969 scf_count_ranges_t
*ranges
)
3971 return (_scf_tmpl_get_count_ranges(t
, SCF_PROPERTY_TM_CONSTRAINT_RANGE
,
3976 scf_tmpl_value_int_range_constraints(const scf_prop_tmpl_t
*t
,
3977 scf_int_ranges_t
*ranges
)
3979 return (_scf_tmpl_get_int_ranges(t
, SCF_PROPERTY_TM_CONSTRAINT_RANGE
,
3984 scf_tmpl_value_count_range_choices(const scf_prop_tmpl_t
*t
,
3985 scf_count_ranges_t
*ranges
)
3987 return (_scf_tmpl_get_count_ranges(t
, SCF_PROPERTY_TM_CHOICES_RANGE
,
3992 scf_tmpl_value_int_range_choices(const scf_prop_tmpl_t
*t
,
3993 scf_int_ranges_t
*ranges
)
3995 return (_scf_tmpl_get_int_ranges(t
, SCF_PROPERTY_TM_CHOICES_RANGE
,
4000 * Returns -1 on failure. Sets scf_error():
4001 * SCF_ERROR_BACKEND_ACCESS
4002 * SCF_ERROR_CONNECTION_BROKEN
4004 * SCF_ERROR_HANDLE_DESTROYED
4005 * SCF_ERROR_INTERNAL
4006 * SCF_ERROR_NO_MEMORY
4007 * SCF_ERROR_NO_RESOURCES
4008 * SCF_ERROR_NOT_BOUND
4009 * SCF_ERROR_NOT_FOUND
4010 * Property doesn't exist or exists and has no value.
4011 * SCF_ERROR_PERMISSION_DENIED
4012 * SCF_ERROR_TEMPLATE_INVALID
4015 scf_tmpl_value_name_choices(const scf_prop_tmpl_t
*t
, scf_values_t
*vals
)
4017 int c_flag
= 0; /* have not read any value yet */
4021 /* First, look for explicitly declared choices. */
4022 if ((ret
= _read_astrings_values(t
->prt_pg
,
4023 SCF_PROPERTY_TM_CHOICES_NAME
, vals
)) != NULL
) {
4025 } else if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4029 /* Next, check for choices included by 'values'. */
4030 if ((r
= _check_choices_include_values(t
->prt_pg
, "values")) == 0) {
4031 /* read values_name */
4034 ret
= _append_astrings_values(t
->prt_pg
,
4035 SCF_PROPERTY_TM_VALUES_NAME
, vals
);
4038 ret
= _read_astrings_values(t
->prt_pg
,
4039 SCF_PROPERTY_TM_VALUES_NAME
, vals
);
4042 } else if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4045 } else if (r
== -1) {
4049 /* Finally check for choices included by 'constraints'. */
4050 if ((r
= _check_choices_include_values(t
->prt_pg
, "constraints")) ==
4052 /* read constraint_name */
4055 ret
= _append_astrings_values(t
->prt_pg
,
4056 SCF_PROPERTY_TM_CONSTRAINT_NAME
, vals
);
4059 ret
= _read_astrings_values(t
->prt_pg
,
4060 SCF_PROPERTY_TM_CONSTRAINT_NAME
, vals
);
4063 } else if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4066 } else if (r
== -1) {
4070 if (c_flag
== 0 || vals
->value_count
== 0) {
4071 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
4078 if (ismember(scf_error(), errors_server
)) {
4080 } else switch (scf_error()) {
4081 case SCF_ERROR_TYPE_MISMATCH
:
4082 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
4085 case SCF_ERROR_NOT_SET
:
4086 case SCF_ERROR_INVALID_ARGUMENT
:
4095 scf_values_destroy(scf_values_t
*vals
)
4098 char **items
= NULL
;
4104 str
= vals
->values_as_strings
;
4107 switch (vals
->value_type
) {
4108 case SCF_TYPE_BOOLEAN
:
4109 free(vals
->values
.v_boolean
);
4111 case SCF_TYPE_COUNT
:
4112 free(vals
->values
.v_count
);
4114 case SCF_TYPE_INTEGER
:
4115 free(vals
->values
.v_integer
);
4117 case SCF_TYPE_ASTRING
:
4118 items
= vals
->values
.v_astring
;
4121 case SCF_TYPE_USTRING
:
4122 items
= vals
->values
.v_ustring
;
4125 case SCF_TYPE_OPAQUE
:
4126 items
= vals
->values
.v_opaque
;
4130 free(vals
->values
.v_time
);
4136 for (i
= 0; i
< vals
->value_count
; ++i
) {
4142 vals
->value_count
= 0;
4148 * char *_make_value_name()
4150 * Construct the prefix for a value common name or value description property.
4151 * It takes the form:
4152 * value_<BASE32 name>_<common_name|description>_
4153 * This is then combined with a localized suffix by the caller to look
4154 * up the property in the repository:
4155 * value_<BASE32 name>_<common_name|description>_<lang>
4157 * Returns NULL on failure. Sets scf_error():
4158 * SCF_ERROR_INVALID_ARGUMENT
4159 * Name isn't short enough make a value name with.
4160 * SCF_ERROR_NO_MEMORY
4163 _make_value_name(char *desc_name
, const char *value
)
4166 char *encoded
= NULL
;
4167 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
4170 encoded
= malloc(sz
);
4171 if (name
== NULL
|| encoded
== NULL
) {
4172 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4178 if (scf_encode32(value
, strlen(value
), encoded
, sz
, NULL
,
4179 SCF_ENCODE32_PAD
) != 0) {
4180 /* Shouldn't happen. */
4184 (void) strlcpy(name
, SCF_PROPERTY_TM_VALUE_PREFIX
, sz
);
4186 if (strlcat(name
, encoded
, sz
) >= sz
) {
4187 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4193 if (strlcat(name
, "_", sz
) >= sz
) {
4194 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4200 if (strlcat(name
, desc_name
, sz
) >= sz
) {
4201 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4207 if (strlcat(name
, "_", sz
) >= sz
) {
4208 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
4219 * ssize_t scf_tmpl_value_common_name()
4221 * Populates "out" with an allocated string containing the value's
4222 * common name. Returns the size of the string on successful return.
4223 * out must be freed with free() on successful return.
4225 * Returns -1 on failure, sets scf_error() to:
4226 * SCF_ERROR_BACKEND_ACCESS
4227 * SCF_ERROR_CONNECTION_BROKEN
4229 * Property group was deleted.
4230 * SCF_ERROR_HANDLE_DESTROYED
4231 * SCF_ERROR_INTERNAL
4232 * SCF_ERROR_INVALID_ARGUMENT
4233 * name not a valid property name
4234 * name and locale are too long to make a property name
4235 * SCF_ERROR_NO_MEMORY
4236 * SCF_ERROR_NO_RESOURCES
4237 * SCF_ERROR_NOT_BOUND
4238 * SCF_ERROR_NOT_FOUND
4239 * Property doesn't exist or exists and has no value.
4240 * SCF_ERROR_PERMISSION_DENIED
4241 * SCF_ERROR_TEMPLATE_INVALID
4242 * property is not SCF_TYPE_ASTRING has more than one value.
4245 scf_tmpl_value_common_name(const scf_prop_tmpl_t
*t
, const char *locale
,
4246 const char *value
, char **out
)
4248 char *value_name
= NULL
;
4250 value_name
= _make_value_name("common_name", value
);
4251 if (value_name
== NULL
)
4254 *out
= _read_localized_astring_from_pg(t
->prt_pg
, value_name
, locale
);
4261 return (strlen(*out
));
4265 * ssize_t scf_tmpl_value_description()
4267 * Populates "out" with an allocated string containing the value's
4268 * description. Returns the size of the string on successful return.
4269 * out must be freed with free() on successful return.
4271 * Returns -1 on failure, sets scf_error() to:
4272 * SCF_ERROR_BACKEND_ACCESS
4273 * SCF_ERROR_CONNECTION_BROKEN
4275 * Property group was deleted.
4276 * SCF_ERROR_HANDLE_DESTROYED
4277 * SCF_ERROR_INTERNAL
4278 * SCF_ERROR_INVALID_ARGUMENT
4279 * name not a valid property name
4280 * name and locale are too long to make a property name
4281 * SCF_ERROR_NO_MEMORY
4282 * SCF_ERROR_NO_RESOURCES
4283 * SCF_ERROR_NOT_BOUND
4284 * SCF_ERROR_NOT_FOUND
4285 * Property doesn't exist or exists and has no value.
4286 * SCF_ERROR_PERMISSION_DENIED
4287 * SCF_ERROR_TEMPLATE_INVALID
4288 * property is not SCF_TYPE_ASTRING has more than one value.
4291 scf_tmpl_value_description(const scf_prop_tmpl_t
*t
, const char *locale
,
4292 const char *value
, char **out
)
4294 char *value_name
= NULL
;
4296 value_name
= _make_value_name("description", value
);
4297 if (value_name
== NULL
)
4301 *out
= _read_localized_astring_from_pg(t
->prt_pg
, value_name
, locale
);
4308 return (strlen(*out
));
4312 * Templates error messages format, in human readable form.
4313 * Each line is one error item:
4315 * prefix error message
4316 * FMRI="err->te_errs->tes_fmri"
4317 * Property group="err->te_pg_name"
4318 * Property name="err->te_prop_name"
4319 * expected value 1="err->te_ev1"
4320 * expected value 2="err->te_ev2"
4321 * actual value="err->te_actual"
4322 * Tempalte source="err->te_tmpl_fmri"
4323 * pg_pattern name="err->tmpl_pg_name"
4324 * pg_pattern type="err->tmpl_pg_type"
4325 * prop_pattern name="err->tmpl_prop_name"
4326 * prop_pattern type="err->tmpl_prop_type"
4328 * To add a new error type, include scf_tmpl_error_type_t in libscf.h
4329 * add one entry in em_desc[], and update the functions pointed by the
4330 * _tmpl_error_access array with the new error code. Also, update the
4331 * scf_tmpl_error_* functions to provide access to desired
4332 * scf_tmpl_error_t fields.
4334 * To add a new error item, add a new field to scf_tmpl_error_t, a new field
4335 * in _scf_tmpl_error_desc or a new non-error-dependent string, add a new entry
4336 * in _tmpl_error_access array and create the appropriate get_val, get_desc
4339 * Changes to both the validation logic and the error types and items must
4340 * be coordinated with the code in svccfg to ensure both libscf and svccfg's
4341 * manifest validation validate the same things.
4345 * Container for all template errors on a validated object.
4347 struct scf_tmpl_errors
{
4350 scf_tmpl_error_t
**tes_errs
;
4352 const char *tes_fmri
;
4353 const char *tes_prefix
;
4354 int tes_flag
; /* if set, scf_tmpl_error_destroy */
4355 /* will free strings in tes_errs */
4359 * Templates error-dependent labels
4361 struct _scf_tmpl_error_desc
{
4365 const char *em_actual
;
4369 * This array MUST be kept in synch with the template error definition of
4370 * scf_tmpl_error_type_t in libscf.h
4372 static struct _scf_tmpl_error_desc em_desc
[] = {
4373 /* SCF_TERR_MISSING_PG */
4374 { "Required property group missing", "Name of missing property group",
4375 "Type of missing property group", NULL
},
4376 /* SCF_TERR_WRONG_PG_TYPE */
4377 { "Property group has bad type", "Specified type", NULL
,
4379 /* SCF_TERR_MISSING_PROP */
4380 { "Required property missing", "Name of missing property", NULL
, NULL
},
4381 /* SCF_TERR_WRONG_PROP_TYPE */
4382 { "Property has bad type", "Specified property type", NULL
,
4383 "Actual property type" },
4384 /* SCF_TERR_CARDINALITY_VIOLATION */
4385 { "Number of property values violates cardinality restriction",
4386 "Cardinality minimum", "Cardinality maximum",
4387 "Actual number of values" },
4388 /* SCF_TERR_VALUE_CONSTRAINT_VIOLATED */
4389 { "Property has illegal value", NULL
, NULL
, "Illegal value" },
4390 /* SCF_TERR_RANGE_VIOLATION */
4391 { "Property value is out of range", NULL
, NULL
, "Actual value" },
4392 /* SCF_TERR_PG_REDEFINE */
4393 { "Instance redefines pg_pattern", "Instance pg_pattern name",
4394 "Instance pg_pattern type", NULL
},
4395 /* SCF_TERR_PROP_TYPE_MISMATCH */
4396 { "Property type and value type mismatch", NULL
, NULL
, "Value type" },
4397 /* SCF_TERR_VALUE_OUT_OF_RANGE */
4398 { "Value is out of range", NULL
, NULL
, "Value" },
4399 /* SCF_TERR_INVALID_VALUE */
4400 { "Value is not valid", NULL
, NULL
, "Value" },
4401 /* SCF_TERR_PG_PATTERN_CONFLICT */
4402 { "Conflicting pg_pattern specifications", "Template source",
4403 "pg_pattern name", "pg_pattern type" },
4404 /* SCF_TERR_PROP_PATTERN_CONFLICT */
4405 { "Conflicting prop_pattern specifications", "Template source",
4406 "prop_pattern name", "prop_pattern type" },
4407 /* SCF_TERR_GENERAL_REDEFINE */
4408 { "Service or instance pg_pattern redefines a global or restarter "
4409 "pg_pattern", "Template source", "pg_pattern name",
4410 "pg_pattern type" },
4411 /* SCF_TERR_INCLUDE_VALUES */
4412 { "Missing constraints or values for include_values element",
4413 "include_values type", NULL
, NULL
},
4414 /* SCF_TERR_PG_PATTERN_INCOMPLETE */
4415 { "Required pg_pattern is missing a name or type attribute",
4417 /* SCF_TERR_PROP_PATTERN_INCOMPLETE */
4418 { "Required prop_pattern is missing a type attribute",
4423 * Templates non error-dependent labels
4425 static const char *em_fmri
= "FMRI";
4426 static const char *em_pg_name
= "Property group";
4427 static const char *em_prop_name
= "Property name";
4428 static const char *em_tmpl_fmri
= "Template source";
4429 static const char *em_tmpl_pg_name
= "pg_pattern name";
4430 static const char *em_tmpl_pg_type
= "pg_pattern type";
4431 static const char *em_tmpl_prop_name
= "prop_pattern name";
4432 static const char *em_tmpl_prop_type
= "prop_pattern type";
4435 _get_fmri_desc(scf_tmpl_error_t
*err
)
4437 switch (err
->te_type
) {
4438 case SCF_TERR_MISSING_PG
:
4439 case SCF_TERR_WRONG_PG_TYPE
:
4440 case SCF_TERR_MISSING_PROP
:
4441 case SCF_TERR_WRONG_PROP_TYPE
:
4442 case SCF_TERR_CARDINALITY_VIOLATION
:
4443 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4444 case SCF_TERR_RANGE_VIOLATION
:
4445 case SCF_TERR_PG_REDEFINE
:
4446 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4447 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4448 case SCF_TERR_INCLUDE_VALUES
:
4449 return (dgettext(TEXT_DOMAIN
, em_fmri
));
4450 case SCF_TERR_PROP_TYPE_MISMATCH
:
4451 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4452 case SCF_TERR_INVALID_VALUE
:
4453 case SCF_TERR_PG_PATTERN_CONFLICT
:
4454 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4455 case SCF_TERR_GENERAL_REDEFINE
:
4462 _get_pg_name_desc(scf_tmpl_error_t
*err
)
4464 switch (err
->te_type
) {
4465 case SCF_TERR_WRONG_PG_TYPE
:
4466 case SCF_TERR_MISSING_PROP
:
4467 case SCF_TERR_WRONG_PROP_TYPE
:
4468 case SCF_TERR_CARDINALITY_VIOLATION
:
4469 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4470 case SCF_TERR_RANGE_VIOLATION
:
4471 return (dgettext(TEXT_DOMAIN
, em_pg_name
));
4472 case SCF_TERR_MISSING_PG
:
4473 case SCF_TERR_PG_REDEFINE
:
4474 case SCF_TERR_PROP_TYPE_MISMATCH
:
4475 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4476 case SCF_TERR_INVALID_VALUE
:
4477 case SCF_TERR_PG_PATTERN_CONFLICT
:
4478 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4479 case SCF_TERR_GENERAL_REDEFINE
:
4480 case SCF_TERR_INCLUDE_VALUES
:
4481 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4482 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4489 _get_prop_name_desc(scf_tmpl_error_t
*err
)
4491 switch (err
->te_type
) {
4492 case SCF_TERR_WRONG_PROP_TYPE
:
4493 case SCF_TERR_CARDINALITY_VIOLATION
:
4494 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4495 case SCF_TERR_RANGE_VIOLATION
:
4496 return (dgettext(TEXT_DOMAIN
, em_prop_name
));
4497 case SCF_TERR_MISSING_PG
:
4498 case SCF_TERR_WRONG_PG_TYPE
:
4499 case SCF_TERR_MISSING_PROP
:
4500 case SCF_TERR_PG_REDEFINE
:
4501 case SCF_TERR_PROP_TYPE_MISMATCH
:
4502 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4503 case SCF_TERR_INVALID_VALUE
:
4504 case SCF_TERR_PG_PATTERN_CONFLICT
:
4505 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4506 case SCF_TERR_GENERAL_REDEFINE
:
4507 case SCF_TERR_INCLUDE_VALUES
:
4508 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4509 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4516 _get_ev1_desc(scf_tmpl_error_t
*err
)
4518 switch (err
->te_type
) {
4519 case SCF_TERR_MISSING_PG
:
4520 case SCF_TERR_WRONG_PG_TYPE
:
4521 case SCF_TERR_MISSING_PROP
:
4522 case SCF_TERR_WRONG_PROP_TYPE
:
4523 case SCF_TERR_CARDINALITY_VIOLATION
:
4524 case SCF_TERR_RANGE_VIOLATION
:
4525 case SCF_TERR_PG_REDEFINE
:
4526 case SCF_TERR_PG_PATTERN_CONFLICT
:
4527 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4528 case SCF_TERR_GENERAL_REDEFINE
:
4529 case SCF_TERR_INCLUDE_VALUES
:
4530 return (dgettext(TEXT_DOMAIN
, em_desc
[err
->te_type
].em_ev1
));
4531 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4532 case SCF_TERR_PROP_TYPE_MISMATCH
:
4533 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4534 case SCF_TERR_INVALID_VALUE
:
4535 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4536 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4543 _get_ev2_desc(scf_tmpl_error_t
*err
)
4545 switch (err
->te_type
) {
4546 case SCF_TERR_MISSING_PG
:
4547 case SCF_TERR_CARDINALITY_VIOLATION
:
4548 case SCF_TERR_RANGE_VIOLATION
:
4549 case SCF_TERR_PG_REDEFINE
:
4550 case SCF_TERR_PG_PATTERN_CONFLICT
:
4551 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4552 case SCF_TERR_GENERAL_REDEFINE
:
4553 return (dgettext(TEXT_DOMAIN
, em_desc
[err
->te_type
].em_ev2
));
4554 case SCF_TERR_WRONG_PG_TYPE
:
4555 case SCF_TERR_MISSING_PROP
:
4556 case SCF_TERR_WRONG_PROP_TYPE
:
4557 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4558 case SCF_TERR_PROP_TYPE_MISMATCH
:
4559 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4560 case SCF_TERR_INVALID_VALUE
:
4561 case SCF_TERR_INCLUDE_VALUES
:
4562 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4563 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4570 _get_actual_desc(scf_tmpl_error_t
*err
)
4572 switch (err
->te_type
) {
4573 case SCF_TERR_MISSING_PG
:
4574 case SCF_TERR_WRONG_PG_TYPE
:
4575 case SCF_TERR_WRONG_PROP_TYPE
:
4576 case SCF_TERR_CARDINALITY_VIOLATION
:
4577 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4578 case SCF_TERR_RANGE_VIOLATION
:
4579 case SCF_TERR_PROP_TYPE_MISMATCH
:
4580 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4581 case SCF_TERR_INVALID_VALUE
:
4582 case SCF_TERR_PG_PATTERN_CONFLICT
:
4583 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4584 case SCF_TERR_GENERAL_REDEFINE
:
4585 case SCF_TERR_INCLUDE_VALUES
:
4586 return (dgettext(TEXT_DOMAIN
,
4587 em_desc
[err
->te_type
].em_actual
));
4588 case SCF_TERR_MISSING_PROP
:
4589 case SCF_TERR_PG_REDEFINE
:
4590 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4591 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4598 _get_tmpl_fmri_desc(scf_tmpl_error_t
*err
)
4600 switch (err
->te_type
) {
4601 case SCF_TERR_MISSING_PG
:
4602 case SCF_TERR_WRONG_PG_TYPE
:
4603 case SCF_TERR_MISSING_PROP
:
4604 case SCF_TERR_WRONG_PROP_TYPE
:
4605 case SCF_TERR_CARDINALITY_VIOLATION
:
4606 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4607 case SCF_TERR_RANGE_VIOLATION
:
4608 case SCF_TERR_PG_REDEFINE
:
4609 case SCF_TERR_PROP_TYPE_MISMATCH
:
4610 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4611 case SCF_TERR_INVALID_VALUE
:
4612 case SCF_TERR_PG_PATTERN_CONFLICT
:
4613 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4614 case SCF_TERR_GENERAL_REDEFINE
:
4615 case SCF_TERR_INCLUDE_VALUES
:
4616 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4617 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4618 return (dgettext(TEXT_DOMAIN
, em_tmpl_fmri
));
4625 _get_tmpl_pg_name_desc(scf_tmpl_error_t
*err
)
4627 switch (err
->te_type
) {
4628 case SCF_TERR_MISSING_PG
:
4629 case SCF_TERR_WRONG_PG_TYPE
:
4630 case SCF_TERR_MISSING_PROP
:
4631 case SCF_TERR_WRONG_PROP_TYPE
:
4632 case SCF_TERR_CARDINALITY_VIOLATION
:
4633 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4634 case SCF_TERR_RANGE_VIOLATION
:
4635 case SCF_TERR_PG_REDEFINE
:
4636 case SCF_TERR_PROP_TYPE_MISMATCH
:
4637 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4638 case SCF_TERR_INVALID_VALUE
:
4639 case SCF_TERR_PG_PATTERN_CONFLICT
:
4640 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4641 case SCF_TERR_GENERAL_REDEFINE
:
4642 case SCF_TERR_INCLUDE_VALUES
:
4643 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4644 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4645 return (dgettext(TEXT_DOMAIN
, em_tmpl_pg_name
));
4652 _get_tmpl_pg_type_desc(scf_tmpl_error_t
*err
)
4654 switch (err
->te_type
) {
4655 case SCF_TERR_MISSING_PG
:
4656 case SCF_TERR_WRONG_PG_TYPE
:
4657 case SCF_TERR_MISSING_PROP
:
4658 case SCF_TERR_WRONG_PROP_TYPE
:
4659 case SCF_TERR_CARDINALITY_VIOLATION
:
4660 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4661 case SCF_TERR_RANGE_VIOLATION
:
4662 case SCF_TERR_PG_REDEFINE
:
4663 case SCF_TERR_PROP_TYPE_MISMATCH
:
4664 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4665 case SCF_TERR_INVALID_VALUE
:
4666 case SCF_TERR_PG_PATTERN_CONFLICT
:
4667 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4668 case SCF_TERR_GENERAL_REDEFINE
:
4669 case SCF_TERR_INCLUDE_VALUES
:
4670 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4671 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4672 return (dgettext(TEXT_DOMAIN
, em_tmpl_pg_type
));
4679 _get_tmpl_prop_name_desc(scf_tmpl_error_t
*err
)
4681 switch (err
->te_type
) {
4682 case SCF_TERR_MISSING_PROP
:
4683 case SCF_TERR_WRONG_PROP_TYPE
:
4684 case SCF_TERR_CARDINALITY_VIOLATION
:
4685 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4686 case SCF_TERR_RANGE_VIOLATION
:
4687 case SCF_TERR_PROP_TYPE_MISMATCH
:
4688 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4689 case SCF_TERR_INVALID_VALUE
:
4690 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4691 case SCF_TERR_INCLUDE_VALUES
:
4692 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4693 return (dgettext(TEXT_DOMAIN
, em_tmpl_prop_name
));
4694 case SCF_TERR_MISSING_PG
:
4695 case SCF_TERR_WRONG_PG_TYPE
:
4696 case SCF_TERR_PG_REDEFINE
:
4697 case SCF_TERR_PG_PATTERN_CONFLICT
:
4698 case SCF_TERR_GENERAL_REDEFINE
:
4699 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4706 _get_tmpl_prop_type_desc(scf_tmpl_error_t
*err
)
4708 switch (err
->te_type
) {
4709 case SCF_TERR_MISSING_PROP
:
4710 case SCF_TERR_WRONG_PROP_TYPE
:
4711 case SCF_TERR_CARDINALITY_VIOLATION
:
4712 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
4713 case SCF_TERR_RANGE_VIOLATION
:
4714 case SCF_TERR_PROP_TYPE_MISMATCH
:
4715 case SCF_TERR_VALUE_OUT_OF_RANGE
:
4716 case SCF_TERR_INVALID_VALUE
:
4717 case SCF_TERR_PROP_PATTERN_CONFLICT
:
4718 case SCF_TERR_INCLUDE_VALUES
:
4719 return (dgettext(TEXT_DOMAIN
, em_tmpl_prop_type
));
4720 case SCF_TERR_MISSING_PG
:
4721 case SCF_TERR_WRONG_PG_TYPE
:
4722 case SCF_TERR_PG_REDEFINE
:
4723 case SCF_TERR_PG_PATTERN_CONFLICT
:
4724 case SCF_TERR_GENERAL_REDEFINE
:
4725 case SCF_TERR_PG_PATTERN_INCOMPLETE
:
4726 case SCF_TERR_PROP_PATTERN_INCOMPLETE
:
4733 _get_fmri_val(scf_tmpl_error_t
*err
)
4735 assert(err
!= NULL
&& err
->te_errs
!= NULL
&&
4736 err
->te_errs
->tes_fmri
!= NULL
);
4737 return (err
->te_errs
->tes_fmri
);
4741 _get_pg_name_val(scf_tmpl_error_t
*err
)
4743 assert(err
!= NULL
);
4744 return (err
->te_pg_name
);
4748 _get_prop_name_val(scf_tmpl_error_t
*err
)
4750 assert(err
!= NULL
);
4751 return (err
->te_prop_name
);
4755 _get_ev1_val(scf_tmpl_error_t
*err
)
4757 assert(err
!= NULL
);
4758 return (err
->te_ev1
);
4762 _get_ev2_val(scf_tmpl_error_t
*err
)
4764 assert(err
!= NULL
);
4765 return (err
->te_ev2
);
4769 _get_actual_val(scf_tmpl_error_t
*err
)
4771 assert(err
!= NULL
);
4772 return (err
->te_actual
);
4776 _get_tmpl_fmri_val(scf_tmpl_error_t
*err
)
4778 assert(err
!= NULL
);
4779 return (err
->te_tmpl_fmri
);
4783 _get_tmpl_pg_name_val(scf_tmpl_error_t
*err
)
4785 assert(err
!= NULL
);
4786 return (err
->te_tmpl_pg_name
);
4790 _get_tmpl_pg_type_val(scf_tmpl_error_t
*err
)
4792 assert(err
!= NULL
);
4793 return (err
->te_tmpl_pg_type
);
4797 _get_tmpl_prop_name_val(scf_tmpl_error_t
*err
)
4799 assert(err
!= NULL
);
4800 return (err
->te_tmpl_prop_name
);
4804 _get_tmpl_prop_type_val(scf_tmpl_error_t
*err
)
4806 assert(err
!= NULL
);
4807 return (err
->te_tmpl_prop_type
);
4811 * Templates error item retrival functions
4813 typedef const char *(*get_em
)(scf_tmpl_error_t
*);
4816 * if new items (lines) are added to the templates error messages,
4817 * new entries in this array (and new fuctions) will be required.
4819 static struct _tmpl_error_access
{
4822 } _tmpl_error_items
[] = {
4823 { (get_em
)_get_fmri_desc
, (get_em
)_get_fmri_val
},
4824 { (get_em
)_get_pg_name_desc
, (get_em
)_get_pg_name_val
},
4825 { (get_em
)_get_prop_name_desc
, (get_em
)_get_prop_name_val
},
4826 { (get_em
)_get_ev1_desc
, (get_em
)_get_ev1_val
},
4827 { (get_em
)_get_ev2_desc
, (get_em
)_get_ev2_val
},
4828 { (get_em
)_get_actual_desc
, (get_em
)_get_actual_val
},
4829 { (get_em
)_get_tmpl_fmri_desc
, (get_em
)_get_tmpl_fmri_val
},
4830 { (get_em
)_get_tmpl_pg_name_desc
, (get_em
)_get_tmpl_pg_name_val
},
4831 { (get_em
)_get_tmpl_pg_type_desc
, (get_em
)_get_tmpl_pg_type_val
},
4832 { (get_em
)_get_tmpl_prop_name_desc
, (get_em
)_get_tmpl_prop_name_val
},
4833 { (get_em
)_get_tmpl_prop_type_desc
, (get_em
)_get_tmpl_prop_type_val
},
4838 * Allocate a new scf_tmpl_error_t and add it to the errs list provided.
4839 * Returns NULL on failure. Sets scf_error():
4840 * SCF_ERROR_NO_MEMORY
4842 static scf_tmpl_error_t
*
4843 _create_error(scf_tmpl_errors_t
*errs
)
4845 scf_tmpl_error_t
*ret
;
4846 scf_tmpl_error_t
**saved_errs
;
4848 assert(errs
!= NULL
);
4849 ret
= calloc(1, sizeof (scf_tmpl_error_t
));
4851 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4855 ret
->te_errs
= errs
;
4857 assert(errs
->tes_num_errs
<= errs
->tes_errs_size
);
4858 if (errs
->tes_num_errs
== errs
->tes_errs_size
) {
4859 /* Time to grow the pointer array. */
4860 saved_errs
= errs
->tes_errs
;
4861 errs
->tes_errs
= calloc(2 * errs
->tes_errs_size
,
4862 sizeof (scf_tmpl_error_t
*));
4863 if (errs
->tes_errs
== NULL
) {
4864 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4865 errs
->tes_errs
= saved_errs
;
4869 (void) memcpy(errs
->tes_errs
, saved_errs
, errs
->tes_errs_size
*
4870 sizeof (scf_tmpl_error_t
*));
4871 errs
->tes_errs_size
= 2 * errs
->tes_errs_size
;
4875 errs
->tes_errs
[errs
->tes_num_errs
] = ret
;
4876 errs
->tes_num_errs
++;
4883 * If destroy_strings is set, scf_tmpl_errors_destroy will free the
4884 * strings in scf_tmpl_error_t entries.
4886 * Returns NULL on failure. Sets scf_error():
4887 * SCF_ERROR_NO_MEMORY
4890 _scf_create_errors(const char *fmri
, int destroy_strings
)
4892 scf_tmpl_errors_t
*ret
;
4895 assert(fmri
!= NULL
);
4897 ret
= calloc(1, sizeof (scf_tmpl_errors_t
));
4899 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4904 ret
->tes_num_errs
= 0;
4905 if ((ret
->tes_fmri
= strdup(fmri
)) == NULL
) {
4906 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4911 ret
->tes_prefix
= strdup("");
4912 if (ret
->tes_prefix
== NULL
) {
4913 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4914 free((char *)ret
->tes_fmri
);
4918 ret
->tes_flag
= destroy_strings
;
4920 /* Make space for a few errors. */
4921 ret
->tes_errs
= calloc(errs_size
, sizeof (scf_tmpl_error_t
*));
4922 if (ret
->tes_errs
== NULL
) {
4923 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4924 free((char *)ret
->tes_fmri
);
4925 free((char *)ret
->tes_prefix
);
4929 ret
->tes_errs_size
= errs_size
;
4935 * return 0 on success, if fails set scf_error() to:
4937 * SCF_ERROR_NO_MEMORY
4940 _scf_tmpl_error_set_prefix(scf_tmpl_errors_t
*errs
, const char *prefix
)
4942 free((void *) errs
->tes_prefix
);
4944 errs
->tes_prefix
= strdup("");
4946 errs
->tes_prefix
= strdup(prefix
);
4947 if (errs
->tes_prefix
== NULL
) {
4948 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
4956 * Returns -1 on failure. Sets scf_error():
4957 * SCF_ERROR_NO_MEMORY
4960 _scf_tmpl_add_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
4961 const char *pg_name
, const char *prop_name
,
4962 const char *ev1
, const char *ev2
, const char *actual
,
4963 const char *tmpl_fmri
, const char *tmpl_pg_name
, const char *tmpl_pg_type
,
4964 const char *tmpl_prop_name
, const char *tmpl_prop_type
)
4966 scf_tmpl_error_t
*err
;
4968 assert(errs
!= NULL
);
4969 assert(tmpl_fmri
!= NULL
);
4971 err
= _create_error(errs
);
4975 err
->te_type
= type
;
4976 err
->te_pg_name
= pg_name
;
4977 err
->te_prop_name
= prop_name
;
4980 err
->te_actual
= actual
;
4981 err
->te_tmpl_fmri
= tmpl_fmri
;
4982 err
->te_tmpl_pg_name
= tmpl_pg_name
;
4983 err
->te_tmpl_pg_type
= tmpl_pg_type
;
4984 err
->te_tmpl_prop_name
= tmpl_prop_name
;
4985 err
->te_tmpl_prop_type
= tmpl_prop_type
;
4991 * returns an allocated string that must be freed with free()
4992 * string contains converted 64-bit integer value
4993 * flag set for signed values
4994 * if fails return NULL and set scf_error() to:
4995 * SCF_ERROR_NO_MEMORY
4998 _val_to_string(uint64_t val
, int flag
)
5000 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
5005 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5010 (void) snprintf(buf
, sz
, "%" PRIu64
, val
);
5012 (void) snprintf(buf
, sz
, "%" PRIi64
, (int64_t)val
);
5018 * return 0 on success, -1 on failure.
5019 * set scf_error() to:
5020 * SCF_ERROR_BACKEND_ACCESS
5021 * SCF_ERROR_CONNECTION_BROKEN
5023 * SCF_ERROR_HANDLE_DESTROYED
5024 * SCF_ERROR_INTERNAL
5025 * SCF_ERROR_NO_MEMORY
5026 * SCF_ERROR_NO_RESOURCES
5027 * SCF_ERROR_NOT_BOUND
5028 * SCF_ERROR_PERMISSION_DENIED
5029 * SCF_ERROR_TEMPLATE_INVALID
5032 _add_tmpl_missing_pg_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
)
5036 char *t_fmri
= NULL
;
5037 char *t_pg_name
= NULL
;
5038 char *t_pg_type
= NULL
;
5040 if ((t_fmri
= _scf_tmpl_get_fmri(t
)) == NULL
)
5042 if (scf_tmpl_pg_name(t
, &t_pg_name
) == -1) {
5045 if (scf_tmpl_pg_type(t
, &t_pg_type
) == -1) {
5048 if ((ev1
= strdup(t_pg_name
)) == NULL
) {
5049 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5052 if ((ev2
= strdup(t_pg_type
)) == NULL
) {
5053 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5057 return (_scf_tmpl_add_error(errs
, SCF_TERR_MISSING_PG
, NULL
, NULL
, ev1
,
5058 ev2
, NULL
, t_fmri
, t_pg_name
, t_pg_type
, NULL
, NULL
));
5069 * return 0 on success, -1 on failure.
5070 * set scf_error() to:
5071 * SCF_ERROR_BACKEND_ACCESS
5072 * SCF_ERROR_CONNECTION_BROKEN
5074 * SCF_ERROR_HANDLE_DESTROYED
5075 * SCF_ERROR_INTERNAL
5076 * SCF_ERROR_NO_MEMORY
5077 * SCF_ERROR_NO_RESOURCES
5078 * SCF_ERROR_NOT_BOUND
5079 * SCF_ERROR_PERMISSION_DENIED
5080 * SCF_ERROR_TEMPLATE_INVALID
5083 _add_tmpl_wrong_pg_type_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
,
5084 scf_propertygroup_t
*pg
)
5086 char *pg_name
= NULL
;
5088 char *actual
= NULL
;
5089 char *t_fmri
= NULL
;
5090 char *t_pg_name
= NULL
;
5091 char *t_pg_type
= NULL
;
5093 if ((t_fmri
= _scf_tmpl_get_fmri(t
)) == NULL
)
5095 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5097 if ((actual
= _scf_get_pg_type(pg
)) == NULL
)
5099 if (scf_tmpl_pg_name(t
, &t_pg_name
) == -1) {
5102 if (scf_tmpl_pg_type(t
, &t_pg_type
) == -1) {
5105 if ((ev1
= strdup(t_pg_type
)) == NULL
) {
5106 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5110 return (_scf_tmpl_add_error(errs
, SCF_TERR_WRONG_PG_TYPE
, pg_name
, NULL
,
5111 ev1
, NULL
, actual
, t_fmri
, t_pg_name
, t_pg_type
, NULL
, NULL
));
5123 * return 0 on success, -1 on failure.
5124 * set scf_error() to:
5125 * SCF_ERROR_BACKEND_ACCESS
5126 * SCF_ERROR_CONNECTION_BROKEN
5128 * SCF_ERROR_HANDLE_DESTROYED
5129 * SCF_ERROR_INTERNAL
5130 * SCF_ERROR_NO_MEMORY
5131 * SCF_ERROR_NO_RESOURCES
5132 * SCF_ERROR_NOT_BOUND
5133 * SCF_ERROR_PERMISSION_DENIED
5134 * SCF_ERROR_TEMPLATE_INVALID
5137 _add_tmpl_missing_prop_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
,
5138 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
)
5140 char *pg_name
= NULL
;
5142 char *t_fmri
= NULL
;
5143 char *t_pg_name
= NULL
;
5144 char *t_pg_type
= NULL
;
5145 char *t_prop_name
= NULL
;
5146 char *t_prop_type
= NULL
;
5148 if ((t_fmri
= _scf_tmpl_get_fmri(t
)) == NULL
)
5150 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5152 if (scf_tmpl_pg_name(t
, &t_pg_name
) == -1) {
5155 if (scf_tmpl_pg_type(t
, &t_pg_type
) == -1) {
5158 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5161 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5162 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5165 } else if (t_prop_type
== NULL
) {
5168 if (t_prop_type
== NULL
)
5169 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5170 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5173 if ((ev1
= strdup(t_prop_name
)) == NULL
) {
5174 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5178 return (_scf_tmpl_add_error(errs
, SCF_TERR_MISSING_PROP
, pg_name
, NULL
,
5179 ev1
, NULL
, NULL
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
,
5193 * return 0 on success, -1 on failure.
5194 * set scf_error() to:
5195 * SCF_ERROR_BACKEND_ACCESS
5196 * SCF_ERROR_CONNECTION_BROKEN
5198 * SCF_ERROR_HANDLE_DESTROYED
5199 * SCF_ERROR_INTERNAL
5200 * SCF_ERROR_NO_MEMORY
5201 * SCF_ERROR_NO_RESOURCES
5202 * SCF_ERROR_NOT_BOUND
5203 * SCF_ERROR_PERMISSION_DENIED
5204 * SCF_ERROR_TEMPLATE_INVALID
5207 _add_tmpl_wrong_prop_type_error(scf_tmpl_errors_t
*errs
,
5208 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
)
5210 char *pg_name
= NULL
;
5211 char *prop_name
= NULL
;
5213 char *actual
= NULL
;
5214 char *t_fmri
= NULL
;
5215 char *t_pg_name
= NULL
;
5216 char *t_pg_type
= NULL
;
5217 char *t_prop_name
= NULL
;
5218 char *t_prop_type
= NULL
;
5220 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5222 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5224 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5226 if ((actual
= _scf_get_prop_type(prop
)) == NULL
)
5228 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5231 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5234 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5237 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5238 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5241 } else if (t_prop_type
== NULL
) {
5244 if (t_prop_type
== NULL
)
5245 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5246 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5249 if ((ev1
= strdup(t_prop_type
)) == NULL
) {
5250 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5254 return (_scf_tmpl_add_error(errs
, SCF_TERR_WRONG_PROP_TYPE
, pg_name
,
5255 prop_name
, ev1
, NULL
, actual
, t_fmri
, t_pg_name
, t_pg_type
,
5256 t_prop_name
, t_prop_type
));
5271 * return 0 on success, -1 on failure.
5272 * set scf_error() to:
5273 * SCF_ERROR_BACKEND_ACCESS
5274 * SCF_ERROR_CONNECTION_BROKEN
5276 * SCF_ERROR_HANDLE_DESTROYED
5277 * SCF_ERROR_INTERNAL
5278 * SCF_ERROR_NO_MEMORY
5279 * SCF_ERROR_NO_RESOURCES
5280 * SCF_ERROR_NOT_BOUND
5281 * SCF_ERROR_PERMISSION_DENIED
5282 * SCF_ERROR_TEMPLATE_INVALID
5285 _add_tmpl_count_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
5286 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
,
5287 uint64_t count
, uint64_t *min
, uint64_t *max
)
5289 char *pg_name
= NULL
;
5290 char *prop_name
= NULL
;
5294 char *t_fmri
= NULL
;
5295 char *t_pg_name
= NULL
;
5296 char *t_pg_type
= NULL
;
5297 char *t_prop_name
= NULL
;
5298 char *t_prop_type
= NULL
;
5300 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5303 case SCF_TERR_RANGE_VIOLATION
:
5304 case SCF_TERR_CARDINALITY_VIOLATION
:
5305 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5307 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5310 case SCF_TERR_VALUE_OUT_OF_RANGE
:
5311 /* keep pg_name = NULL and prop_name = NULL */
5314 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5317 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5320 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5323 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5324 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5327 } else if (t_prop_type
== NULL
) {
5330 if (t_prop_type
== NULL
)
5331 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5332 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5336 if ((s_min
= strdup("")) == NULL
) {
5337 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5341 if ((s_min
= _val_to_string(*min
, 0)) == NULL
) {
5342 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5347 if ((s_max
= strdup("")) == NULL
) {
5348 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5352 if ((s_max
= _val_to_string(*max
, 0)) == NULL
) {
5353 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5357 if ((num
= _val_to_string(count
, 0)) == NULL
) {
5358 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5362 return (_scf_tmpl_add_error(errs
, type
, pg_name
, prop_name
, s_min
,
5363 s_max
, num
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
,
5380 * return 0 on success, -1 on failure.
5381 * set scf_error() to:
5382 * SCF_ERROR_BACKEND_ACCESS
5383 * SCF_ERROR_CONNECTION_BROKEN
5385 * SCF_ERROR_HANDLE_DESTROYED
5386 * SCF_ERROR_INTERNAL
5387 * SCF_ERROR_NO_MEMORY
5388 * SCF_ERROR_NO_RESOURCES
5389 * SCF_ERROR_NOT_BOUND
5390 * SCF_ERROR_PERMISSION_DENIED
5391 * SCF_ERROR_TEMPLATE_INVALID
5394 _add_tmpl_constraint_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
5395 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
,
5398 scf_type_t val_type
;
5399 char *pg_name
= NULL
;
5400 char *prop_name
= NULL
;
5402 char *t_fmri
= NULL
;
5403 char *t_pg_name
= NULL
;
5404 char *t_pg_type
= NULL
;
5405 char *t_prop_name
= NULL
;
5406 char *t_prop_type
= NULL
;
5408 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5411 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
5412 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5414 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5417 case SCF_TERR_INVALID_VALUE
:
5418 /* keep pg_name = NULL and prop_name = NULL */
5419 if ((value
= _scf_value_get_as_string(val
)) == NULL
)
5422 case SCF_TERR_PROP_TYPE_MISMATCH
:
5423 /* keep pg_name = NULL and prop_name = NULL */
5424 /* use value for value type */
5425 val_type
= scf_value_type(val
);
5426 if ((value
= strdup(scf_type_to_string(val_type
))) ==
5428 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5433 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5436 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5439 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5442 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5443 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5446 } else if (t_prop_type
== NULL
) {
5449 if (t_prop_type
== NULL
)
5450 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5451 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5455 return (_scf_tmpl_add_error(errs
, type
, pg_name
, prop_name
, NULL
, NULL
,
5456 value
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
, t_prop_type
));
5458 assert(scf_error() != SCF_ERROR_NOT_SET
);
5471 * return 0 on success, -1 on failure.
5472 * set scf_error() to:
5473 * SCF_ERROR_BACKEND_ACCESS
5474 * SCF_ERROR_CONNECTION_BROKEN
5476 * SCF_ERROR_HANDLE_DESTROYED
5477 * SCF_ERROR_INTERNAL
5478 * SCF_ERROR_NO_MEMORY
5479 * SCF_ERROR_NO_RESOURCES
5480 * SCF_ERROR_NOT_BOUND
5481 * SCF_ERROR_PERMISSION_DENIED
5482 * SCF_ERROR_TEMPLATE_INVALID
5485 _add_tmpl_int_error(scf_tmpl_errors_t
*errs
, scf_tmpl_error_type_t type
,
5486 scf_propertygroup_t
*pg
, const scf_prop_tmpl_t
*pt
, scf_property_t
*prop
,
5487 int64_t val
, int64_t *min
, int64_t *max
)
5489 char *pg_name
= NULL
;
5490 char *prop_name
= NULL
;
5494 char *t_fmri
= NULL
;
5495 char *t_pg_name
= NULL
;
5496 char *t_pg_type
= NULL
;
5497 char *t_prop_name
= NULL
;
5498 char *t_prop_type
= NULL
;
5500 if ((t_fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5504 case SCF_TERR_RANGE_VIOLATION
:
5505 if ((pg_name
= _scf_get_pg_name(pg
)) == NULL
)
5507 if ((prop_name
= _scf_get_prop_name(prop
)) == NULL
)
5510 case SCF_TERR_VALUE_OUT_OF_RANGE
:
5511 /* keep pg_name = NULL and prop_name = NULL */
5514 if (scf_tmpl_pg_name(pt
->prt_t
, &t_pg_name
) == -1) {
5517 if (scf_tmpl_pg_type(pt
->prt_t
, &t_pg_type
) == -1) {
5520 if (scf_tmpl_prop_name(pt
, &t_prop_name
) == -1) {
5523 t_prop_type
= _scf_read_tmpl_prop_type_as_string(pt
);
5524 if (t_prop_type
!= NULL
&& t_prop_type
[0] == '\0') {
5527 } else if (t_prop_type
== NULL
) {
5530 if (t_prop_type
== NULL
)
5531 if ((t_prop_type
= strdup(SCF_TMPL_WILDCARD
)) == NULL
) {
5532 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5536 if ((s_min
= strdup("")) == NULL
) {
5537 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5541 if ((s_min
= _val_to_string(*((uint64_t *)min
), 1)) == NULL
) {
5542 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5547 if ((s_max
= strdup("")) == NULL
) {
5548 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5552 if ((s_max
= _val_to_string(*((uint64_t *)max
), 1)) == NULL
) {
5553 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5557 if ((value
= _val_to_string((uint64_t)val
, 1)) == NULL
) {
5558 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5562 return (_scf_tmpl_add_error(errs
, type
, pg_name
, prop_name
, s_min
,
5563 s_max
, value
, t_fmri
, t_pg_name
, t_pg_type
, t_prop_name
,
5580 * return 0 on success, -1 on failure.
5581 * set scf_error() to:
5582 * SCF_ERROR_BACKEND_ACCESS
5583 * SCF_ERROR_CONNECTION_BROKEN
5585 * SCF_ERROR_HANDLE_DESTROYED
5586 * SCF_ERROR_INTERNAL
5587 * SCF_ERROR_NO_MEMORY
5588 * SCF_ERROR_NO_RESOURCES
5589 * SCF_ERROR_NOT_BOUND
5590 * SCF_ERROR_PERMISSION_DENIED
5591 * SCF_ERROR_TEMPLATE_INVALID
5594 _add_tmpl_pg_redefine_error(scf_tmpl_errors_t
*errs
, scf_pg_tmpl_t
*t
,
5599 char *t_fmri
= NULL
;
5600 char *t_pg_name
= NULL
;
5601 char *t_pg_type
= NULL
;
5603 if ((t_fmri
= _scf_tmpl_get_fmri(r
)) == NULL
)
5605 if (scf_tmpl_pg_name(r
, &t_pg_name
) == -1) {
5608 if (scf_tmpl_pg_type(r
, &t_pg_type
) == -1) {
5611 if (scf_tmpl_pg_name(t
, &ev1
) == -1) {
5614 if (scf_tmpl_pg_type(t
, &ev2
) == -1) {
5618 return (_scf_tmpl_add_error(errs
, SCF_TERR_PG_REDEFINE
, NULL
, NULL
,
5619 ev1
, ev2
, NULL
, t_fmri
, t_pg_name
, t_pg_type
, NULL
, NULL
));
5630 * return 0 if value is within count ranges constraint.
5631 * return -1 otherwise
5634 _check_count_ranges(scf_count_ranges_t
*cr
, uint64_t v
)
5638 for (i
= 0; i
< cr
->scr_num_ranges
; ++i
) {
5639 if (v
>= cr
->scr_min
[i
] &&
5640 v
<= cr
->scr_max
[i
]) {
5641 /* value is within ranges constraint */
5649 * return 0 if value is within count ranges constraint.
5650 * return -1 otherwise
5653 _check_int_ranges(scf_int_ranges_t
*ir
, int64_t v
)
5657 for (i
= 0; i
< ir
->sir_num_ranges
; ++i
) {
5658 if (v
>= ir
->sir_min
[i
] &&
5659 v
<= ir
->sir_max
[i
]) {
5660 /* value is within integer ranges constraint */
5668 * int _value_in_constraint()
5670 * Checks whether the supplied value violates any of the constraints
5671 * specified in the supplied property template. If it does, an appropriate
5672 * error is appended to "errs". pg and prop, if supplied, are used to
5673 * augment the information in the error. Returns 0 on success.
5675 * Returns -1 on failure. Sets scf_error():
5676 * SCF_ERROR_BACKEND_ACCESS
5677 * SCF_ERROR_CONNECTION_BROKEN
5679 * SCF_ERROR_HANDLE_DESTROYED
5680 * SCF_ERROR_INTERNAL
5681 * SCF_ERROR_INVALID_ARGUMENT
5682 * SCF_ERROR_NO_MEMORY
5683 * SCF_ERROR_NO_RESOURCES
5684 * SCF_ERROR_NOT_BOUND
5685 * SCF_ERROR_PERMISSION_DENIED
5686 * SCF_ERROR_TEMPLATE_INVALID
5689 _value_in_constraint(scf_propertygroup_t
*pg
, scf_property_t
*prop
,
5690 const scf_prop_tmpl_t
*pt
, scf_value_t
*value
, scf_tmpl_errors_t
*errs
)
5692 scf_type_t type
, tmpl_type
;
5694 scf_tmpl_error_type_t terr_type
;
5698 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
5704 scf_count_ranges_t cr
;
5705 scf_int_ranges_t ir
;
5707 type
= scf_value_type(value
);
5708 if (type
== SCF_TYPE_INVALID
) {
5709 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
5713 /* Check if template type matches value type. */
5714 if (scf_tmpl_prop_type(pt
, &tmpl_type
) == -1) {
5715 if (scf_error() != SCF_ERROR_NOT_FOUND
)
5716 /* type is not wildcarded */
5718 } else if (tmpl_type
!= type
) {
5720 if (pg
== NULL
&& prop
== NULL
) {
5721 if (_add_tmpl_constraint_error(errs
,
5722 SCF_TERR_PROP_TYPE_MISMATCH
, NULL
, pt
,
5730 /* Numeric values should be checked against any range constraints. */
5732 case SCF_TYPE_COUNT
:
5733 r
= scf_value_get_count(value
, &v_count
);
5736 if (scf_tmpl_value_count_range_constraints(pt
, &cr
) != 0) {
5737 if (scf_error() == SCF_ERROR_NOT_FOUND
)
5739 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
)
5740 (void) scf_set_error(
5741 SCF_ERROR_TEMPLATE_INVALID
);
5744 if (_check_count_ranges(&cr
, v_count
) == 0) {
5745 /* value is within ranges constraint */
5746 scf_count_ranges_destroy(&cr
);
5749 scf_count_ranges_destroy(&cr
);
5753 * If we get here, we have a possible constraint
5756 err_flag
|= 0x1; /* RANGE_VIOLATION, count */
5758 case SCF_TYPE_INTEGER
:
5759 if (scf_value_get_integer(value
, &v_int
) != 0)
5761 if (scf_tmpl_value_int_range_constraints(pt
, &ir
) != 0) {
5762 if (scf_error() == SCF_ERROR_NOT_FOUND
)
5764 if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED
)
5765 (void) scf_set_error(
5766 SCF_ERROR_TEMPLATE_INVALID
);
5769 if (_check_int_ranges(&ir
, v_int
) == 0) {
5770 /* value is within ranges constraint */
5771 scf_int_ranges_destroy(&ir
);
5774 scf_int_ranges_destroy(&ir
);
5777 * If we get here, we have a possible constraint
5780 err_flag
|= 0x2; /* RANGE_VIOLATION, integer */
5788 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
5793 * If a set of names is provided, confirm value has one of
5796 if (scf_tmpl_value_name_constraints(pt
, &vals
) != 0) {
5798 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
5802 r
= scf_value_get_as_string_typed(value
, type
, vstr
, sz
);
5805 * All errors (INVALID_ARGUMENT, NOT_SET, TYPE_MISMATCH)
5806 * should be impossible or already caught above.
5810 constraints
= vals
.values
.v_astring
;
5811 for (n
= 0; constraints
[n
] != NULL
; ++n
) {
5812 if (strcmp(constraints
[n
], vstr
) == 0) {
5813 /* value is within constraint */
5814 scf_values_destroy(&vals
);
5819 /* if we get here, we have a constraint violation */
5820 err_flag
|= 0x4; /* CONSTRAINT_VIOLATED */
5821 scf_values_destroy(&vals
);
5826 /* register the errors found */
5827 if (ret
== 1 && errs
!= NULL
) {
5828 if ((err_flag
& 0x1) == 0x1) {
5830 * Help make the error more human-friendly. If
5831 * pg and prop are provided, we know we're
5832 * validating repository data. If they're not,
5833 * we're validating a potentially hypothetical
5836 if (pg
== NULL
&& prop
== NULL
)
5837 terr_type
= SCF_TERR_VALUE_OUT_OF_RANGE
;
5839 terr_type
= SCF_TERR_RANGE_VIOLATION
;
5840 if (_add_tmpl_count_error(errs
, terr_type
, pg
, pt
,
5841 prop
, v_count
, 0, 0) == -1)
5844 if ((err_flag
& 0x2) == 0x2) {
5845 if (pg
== NULL
&& prop
== NULL
)
5846 terr_type
= SCF_TERR_VALUE_OUT_OF_RANGE
;
5848 terr_type
= SCF_TERR_RANGE_VIOLATION
;
5849 if (_add_tmpl_int_error(errs
, terr_type
, pg
, pt
, prop
,
5853 if ((err_flag
& 0x4) == 0x4) {
5854 if (pg
== NULL
&& prop
== NULL
)
5855 terr_type
= SCF_TERR_INVALID_VALUE
;
5857 terr_type
= SCF_TERR_VALUE_CONSTRAINT_VIOLATED
;
5858 if (_add_tmpl_constraint_error(errs
, terr_type
, pg
,
5859 pt
, prop
, value
) == -1)
5867 * Returns -1 on failure. Sets scf_error():
5868 * SCF_ERROR_BACKEND_ACCESS
5869 * SCF_ERROR_CONNECTION_BROKEN
5871 * SCF_ERROR_HANDLE_DESTROYED
5872 * SCF_ERROR_INTERNAL
5873 * SCF_ERROR_INVALID_ARGUMENT
5874 * SCF_ERROR_NO_MEMORY
5875 * SCF_ERROR_NO_RESOURCES
5876 * SCF_ERROR_NOT_BOUND
5877 * SCF_ERROR_PERMISSION_DENIED
5878 * SCF_ERROR_TEMPLATE_INVALID
5881 scf_tmpl_value_in_constraint(const scf_prop_tmpl_t
*pt
, scf_value_t
*value
,
5882 scf_tmpl_errors_t
**errs
)
5884 scf_tmpl_errors_t
*e
= NULL
;
5889 if ((fmri
= _scf_tmpl_get_fmri(pt
->prt_t
)) == NULL
)
5891 *errs
= _scf_create_errors(fmri
, 1);
5898 return (_value_in_constraint(NULL
, NULL
, pt
, value
, e
));
5902 scf_tmpl_next_error(scf_tmpl_errors_t
*errs
)
5904 if (errs
->tes_index
< errs
->tes_num_errs
) {
5905 assert(errs
->tes_errs
[errs
->tes_index
] != NULL
);
5906 return (errs
->tes_errs
[errs
->tes_index
++]);
5913 scf_tmpl_reset_errors(scf_tmpl_errors_t
*errs
)
5915 errs
->tes_index
= 0;
5919 scf_tmpl_strerror(scf_tmpl_error_t
*err
, char *s
, size_t n
, int flag
)
5924 int nsz
= 0; /* err msg length */
5925 int sz
= n
; /* available buffer size */
5926 char *buf
= s
; /* where to append in buffer */
5927 char *s0
= (flag
== SCF_TMPL_STRERROR_HUMAN
) ? ":\n\t" : ": ";
5928 char *s1
= (flag
== SCF_TMPL_STRERROR_HUMAN
) ? "\n\t" : "; ";
5933 if (err
->te_errs
->tes_prefix
!= NULL
) {
5934 ret
= snprintf(buf
, sz
, "%s", dgettext(TEXT_DOMAIN
,
5935 err
->te_errs
->tes_prefix
));
5937 sz
= (sz
- ret
) > 0 ? sz
- ret
: 0;
5938 buf
= (sz
> 0) ? s
+ nsz
: NULL
;
5941 ret
= snprintf(buf
, sz
, "%s", dgettext(TEXT_DOMAIN
,
5942 em_desc
[err
->te_type
].em_msg
));
5944 sz
= (sz
- ret
) > 0 ? sz
- ret
: 0;
5945 buf
= (sz
> 0) ? s
+ nsz
: NULL
;
5947 for (i
= 0; _tmpl_error_items
[i
].get_desc
!= NULL
; ++i
) {
5948 if ((str
= _tmpl_error_items
[i
].get_desc(err
)) == NULL
)
5949 /* no item to print */
5951 val
= _tmpl_error_items
[i
].get_val(err
);
5952 ret
= snprintf(buf
, sz
, "%s%s=\"%s\"", sep
, str
,
5953 (val
== NULL
) ? "" : val
);
5955 sz
= (sz
- ret
) > 0 ? sz
- ret
: 0;
5956 buf
= (sz
> 0) ? s
+ nsz
: NULL
;
5963 * return 0 on success, -1 on failure.
5964 * set scf_error() to:
5965 * SCF_ERROR_BACKEND_ACCESS
5966 * SCF_ERROR_CONNECTION_BROKEN
5968 * SCF_ERROR_HANDLE_DESTROYED
5969 * SCF_ERROR_INTERNAL
5970 * SCF_ERROR_NO_MEMORY
5971 * SCF_ERROR_NO_RESOURCES
5972 * SCF_ERROR_NOT_BOUND
5973 * SCF_ERROR_PERMISSION_DENIED
5974 * SCF_ERROR_TEMPLATE_INVALID
5977 _validate_cardinality(scf_propertygroup_t
*pg
, scf_prop_tmpl_t
*pt
,
5978 scf_property_t
*prop
, scf_tmpl_errors_t
*errs
)
5982 scf_iter_t
*iter
= NULL
;
5983 scf_value_t
*val
= NULL
;
5988 if (scf_tmpl_prop_cardinality(pt
, &min
, &max
) != 0) {
5989 if (scf_error() == SCF_ERROR_NOT_FOUND
)
5995 /* Any number of values permitted. Just return success. */
5996 if (min
== 0 && max
== UINT64_MAX
) {
6000 h
= scf_property_handle(prop
);
6002 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
6006 iter
= scf_iter_create(h
);
6007 val
= scf_value_create(h
);
6008 if (iter
== NULL
|| val
== NULL
) {
6009 if (ismember(scf_error(), errors_server
)) {
6017 if (scf_iter_property_values(iter
, prop
) != 0) {
6018 if (ismember(scf_error(), errors_server
)) {
6026 while ((r
= scf_iter_next_value(iter
, val
)) == 1)
6030 if (ismember(scf_error(), errors_server
)) {
6038 if (count
< min
|| count
> max
)
6039 if (_add_tmpl_count_error(errs
, SCF_TERR_CARDINALITY_VIOLATION
,
6040 pg
, pt
, prop
, (uint64_t)count
, &min
, &max
) == -1)
6046 scf_iter_destroy(iter
);
6047 scf_value_destroy(val
);
6052 * Returns -1 on error. Sets scf_error():
6053 * SCF_ERROR_BACKEND_ACCESS
6054 * SCF_ERROR_CONNECTION_BROKEN
6056 * SCF_ERROR_HANDLE_DESTROYED
6057 * SCF_ERROR_INTERNAL
6058 * SCF_ERROR_NO_MEMORY
6059 * SCF_ERROR_NO_RESOURCES
6060 * SCF_ERROR_NOT_BOUND
6061 * SCF_ERROR_PERMISSION_DENIED
6062 * SCF_ERROR_TEMPLATE_INVALID
6065 _check_property(scf_prop_tmpl_t
*pt
, scf_propertygroup_t
*pg
,
6066 scf_property_t
*prop
, scf_tmpl_errors_t
*errs
)
6068 scf_type_t tmpl_type
;
6071 scf_iter_t
*iter
= NULL
;
6072 scf_value_t
*val
= NULL
;
6076 h
= scf_pg_handle(pg
);
6078 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
6082 iter
= scf_iter_create(h
);
6083 val
= scf_value_create(h
);
6084 if (iter
== NULL
|| val
== NULL
) {
6085 if (ismember(scf_error(), errors_server
)) {
6086 scf_iter_destroy(iter
);
6087 scf_value_destroy(val
);
6095 if (scf_tmpl_prop_required(pt
, &required
) != 0)
6099 if (scf_tmpl_prop_type(pt
, &tmpl_type
) == -1) {
6100 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
6102 } else if (required
) {
6103 /* If required, type must be specified. */
6104 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6107 } else if (scf_property_is_type(prop
, tmpl_type
) != 0) {
6108 if (ismember(scf_error(), errors_server
)) {
6110 } else switch (scf_error()) {
6111 case SCF_ERROR_TYPE_MISMATCH
:
6112 if (_add_tmpl_wrong_prop_type_error(errs
, pg
, pt
,
6117 case SCF_ERROR_INVALID_ARGUMENT
:
6119 * tmpl_prop_type shouldn't have handed back
6120 * an invalid property type.
6122 case SCF_ERROR_NOT_SET
:
6131 if (_validate_cardinality(pg
, pt
, prop
, errs
) == -1)
6134 /* Value constraints */
6136 * Iterate through each value, and confirm it is defined as
6139 if (scf_iter_property_values(iter
, prop
) != 0) {
6140 assert(scf_error() != SCF_ERROR_NOT_SET
&&
6141 scf_error() != SCF_ERROR_HANDLE_MISMATCH
);
6145 while ((r
= scf_iter_next_value(iter
, val
)) == 1) {
6146 if (_value_in_constraint(pg
, prop
, pt
, val
, errs
) == -1) {
6147 if (ismember(scf_error(), errors_server
)) {
6149 } else switch (scf_error()) {
6150 case SCF_ERROR_TEMPLATE_INVALID
:
6153 case SCF_ERROR_INVALID_ARGUMENT
:
6162 if (ismember(scf_error(), errors_server
)) {
6173 scf_iter_destroy(iter
);
6174 scf_value_destroy(val
);
6179 * Returns -1 on failure, sets scf_error() to:
6180 * SCF_ERROR_BACKEND_ACCESS
6181 * SCF_ERROR_CONNECTION_BROKEN
6183 * SCF_ERROR_HANDLE_DESTROYED
6184 * SCF_ERROR_INTERNAL
6185 * SCF_ERROR_NO_MEMORY
6186 * SCF_ERROR_NO_RESOURCES
6187 * SCF_ERROR_NOT_BOUND
6188 * SCF_ERROR_PERMISSION_DENIED
6189 * SCF_ERROR_TEMPLATE_INVALID
6192 _check_pg(scf_pg_tmpl_t
*t
, scf_propertygroup_t
*pg
, char *pg_name
,
6193 char *type
, scf_tmpl_errors_t
*errs
)
6195 scf_prop_tmpl_t
*pt
= NULL
;
6196 char *pg_type
= NULL
;
6197 scf_iter_t
*iter
= NULL
;
6198 uint8_t pg_required
;
6199 scf_property_t
*prop
= NULL
;
6202 char *prop_name
= NULL
;
6203 ssize_t nsize
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
6206 assert(pg_name
!= NULL
);
6209 assert(type
!= NULL
);
6212 if ((h
= scf_pg_handle(pg
)) == NULL
) {
6213 assert(scf_error() == SCF_ERROR_HANDLE_DESTROYED
);
6216 if ((pt
= scf_tmpl_prop_create(h
)) == NULL
) {
6217 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
6221 if ((prop
= scf_property_create(h
)) == NULL
) {
6222 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
6226 if ((iter
= scf_iter_create(h
)) == NULL
) {
6227 assert(scf_error() != SCF_ERROR_INVALID_ARGUMENT
);
6230 if ((prop_name
= malloc(nsize
)) == NULL
) {
6231 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
6235 if (scf_tmpl_pg_required(t
, &pg_required
) != 0)
6238 if (scf_tmpl_pg_type(t
, &pg_type
) == -1) {
6240 } else if (pg_required
!= 0 &&
6241 strcmp(SCF_TMPL_WILDCARD
, pg_type
) == 0) {
6242 /* Type must be specified for required pgs. */
6243 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6247 if (pg_type
!= NULL
) {
6248 if (strcmp(pg_type
, type
) != 0 &&
6249 strcmp(pg_type
, SCF_TMPL_WILDCARD
) != 0) {
6250 if (_add_tmpl_wrong_pg_type_error(errs
, t
, pg
) == -1)
6256 /* Iterate through properties in the repository and check them. */
6257 if (scf_iter_pg_properties(iter
, pg
) != 0) {
6258 if (ismember(scf_error(), errors_server
)) {
6266 while ((r
= scf_iter_next_property(iter
, prop
)) == 1) {
6267 if (scf_property_get_name(prop
, prop_name
, nsize
) == -1) {
6268 assert(scf_error() != SCF_ERROR_NOT_SET
);
6271 if (scf_tmpl_get_by_prop(t
, prop_name
, pt
, 0) != 0) {
6272 if (ismember(scf_error(), errors_server
)) {
6274 } else switch (scf_error()) {
6275 case SCF_ERROR_NOT_FOUND
:
6276 /* No template. Continue. */
6279 case SCF_ERROR_INVALID_ARGUMENT
:
6286 if (_check_property(pt
, pg
, prop
, errs
) != 0)
6291 if (ismember(scf_error(), errors_server
)) {
6299 scf_tmpl_prop_reset(pt
);
6303 * Confirm required properties are present.
6305 while ((r
= scf_tmpl_iter_props(t
, pt
,
6306 SCF_PROP_TMPL_FLAG_REQUIRED
)) == 0) {
6307 scf_type_t prop_type
;
6309 if (scf_tmpl_prop_name(pt
, &prop_name
) == -1)
6312 /* required properties cannot have type wildcarded */
6313 if (scf_tmpl_prop_type(pt
, &prop_type
) == -1) {
6314 if (scf_error() == SCF_ERROR_NOT_FOUND
)
6315 (void) scf_set_error(
6316 SCF_ERROR_TEMPLATE_INVALID
);
6320 if (scf_pg_get_property(pg
, prop_name
, prop
) != 0) {
6321 if (ismember(scf_error(), errors_server
)) {
6323 } else switch (scf_error()) {
6324 case SCF_ERROR_NOT_FOUND
:
6325 if (_add_tmpl_missing_prop_error(errs
, t
, pg
,
6330 case SCF_ERROR_INVALID_ARGUMENT
:
6331 (void) scf_set_error(
6332 SCF_ERROR_TEMPLATE_INVALID
);
6335 case SCF_ERROR_HANDLE_MISMATCH
:
6336 case SCF_ERROR_NOT_SET
:
6346 if (ismember(scf_error(), errors_server
)) {
6348 } else switch (scf_error()) {
6349 case SCF_ERROR_NOT_FOUND
:
6352 case SCF_ERROR_TEMPLATE_INVALID
:
6355 case SCF_ERROR_INVALID_ARGUMENT
:
6364 scf_tmpl_prop_destroy(pt
);
6365 scf_iter_destroy(iter
);
6366 scf_property_destroy(prop
);
6373 * Checks if instance fmri redefines any pgs defined in restarter or global
6374 * Return -1 on failure, sets scf_error() to:
6375 * SCF_ERROR_BACKEND_ACCESS
6376 * SCF_ERROR_CONNECTION_BROKEN
6378 * SCF_ERROR_HANDLE_DESTROYED
6379 * SCF_ERROR_INTERNAL
6380 * SCF_ERROR_INVALID_ARGUMENT
6381 * SCF_ERROR_NO_MEMORY
6382 * SCF_ERROR_NO_RESOURCES
6383 * SCF_ERROR_NOT_BOUND
6384 * SCF_ERROR_NOT_FOUND
6385 * SCF_ERROR_PERMISSION_DENIED
6386 * SCF_ERROR_TEMPLATE_INVALID
6389 _scf_tmpl_check_pg_redef(scf_handle_t
*h
, const char *fmri
,
6390 const char *snapname
, scf_tmpl_errors_t
*errs
)
6392 scf_pg_tmpl_t
*t
= NULL
;
6393 scf_pg_tmpl_t
*r
= NULL
;
6394 char *pg_name
= NULL
;
6395 char *pg_name_r
= NULL
;
6396 char *pg_type
= NULL
;
6397 char *pg_type_r
= NULL
;
6398 char *target
= NULL
;
6402 t
= scf_tmpl_pg_create(h
);
6403 r
= scf_tmpl_pg_create(h
);
6404 if (t
== NULL
|| r
== NULL
)
6407 while ((ret
= scf_tmpl_iter_pgs(t
, fmri
, snapname
, NULL
,
6408 SCF_PG_TMPL_FLAG_EXACT
)) == 1) {
6409 if (scf_tmpl_pg_name(t
, &pg_name
) == -1) {
6412 if (scf_tmpl_pg_type(t
, &pg_type
) == -1) {
6415 /* look for a redefinition of a global/restarter pg_pattern */
6416 while ((ret
= scf_tmpl_iter_pgs(r
, fmri
, snapname
, pg_type
,
6418 if (scf_tmpl_pg_name(r
, &pg_name_r
) == -1) {
6420 } else if (strcmp(pg_name_r
, SCF_TMPL_WILDCARD
) != 0 &&
6421 strcmp(pg_name
, SCF_TMPL_WILDCARD
) != 0 &&
6422 strcmp(pg_name
, pg_name_r
) != 0) {
6428 if (scf_tmpl_pg_type(r
, &pg_type_r
) == -1) {
6430 } else if (strcmp(pg_type_r
, SCF_TMPL_WILDCARD
) != 0 &&
6431 strcmp(pg_type
, SCF_TMPL_WILDCARD
) != 0 &&
6432 strcmp(pg_type
, pg_type_r
) != 0) {
6440 if (scf_tmpl_pg_target(r
, &target
) == -1) {
6444 if (strcmp(target
, SCF_TM_TARGET_ALL
) == 0 ||
6445 strcmp(target
, SCF_TM_TARGET_DELEGATE
) == 0) {
6446 /* found a pg_pattern redefinition */
6447 if (_add_tmpl_pg_redefine_error(errs
, t
,
6467 scf_tmpl_pg_reset(r
);
6480 scf_tmpl_pg_destroy(t
);
6481 scf_tmpl_pg_destroy(r
);
6488 if (ret_val
== -1) {
6489 if (!ismember(scf_error(), errors_server
)) {
6490 switch (scf_error()) {
6491 case SCF_ERROR_TYPE_MISMATCH
:
6492 (void) scf_set_error(
6493 SCF_ERROR_TEMPLATE_INVALID
);
6496 case SCF_ERROR_CONSTRAINT_VIOLATED
:
6497 case SCF_ERROR_INVALID_ARGUMENT
:
6498 case SCF_ERROR_NOT_FOUND
:
6499 case SCF_ERROR_TEMPLATE_INVALID
:
6502 case SCF_ERROR_HANDLE_MISMATCH
:
6503 case SCF_ERROR_NOT_SET
:
6514 * Returns -1 on failure, sets scf_error() to:
6515 * SCF_ERROR_BACKEND_ACCESS
6516 * SCF_ERROR_CONNECTION_BROKEN
6518 * SCF_ERROR_HANDLE_DESTROYED
6519 * SCF_ERROR_INTERNAL
6520 * SCF_ERROR_INVALID_ARGUMENT
6521 * SCF_ERROR_NO_MEMORY
6522 * SCF_ERROR_NO_RESOURCES
6523 * SCF_ERROR_NOT_BOUND
6524 * SCF_ERROR_NOT_FOUND
6525 * SCF_ERROR_PERMISSION_DENIED
6526 * SCF_ERROR_TEMPLATE_INVALID
6529 scf_tmpl_validate_fmri(scf_handle_t
*h
, const char *fmri
, const char *snapshot
,
6530 scf_tmpl_errors_t
**errs
, int flags
)
6532 scf_pg_tmpl_t
*t
= NULL
;
6533 scf_iter_t
*iter
= NULL
;
6534 scf_propertygroup_t
*pg
= NULL
;
6535 scf_instance_t
*inst
= NULL
;
6536 scf_snapshot_t
*snap
= NULL
;
6538 char *pg_name
= NULL
;
6539 ssize_t rsize
= scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH
) + 1;
6540 ssize_t nsize
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
6544 assert(errs
!= NULL
);
6546 if ((*errs
= _scf_create_errors(fmri
, 1)) == NULL
)
6549 if ((pg
= scf_pg_create(h
)) == NULL
||
6550 (iter
= scf_iter_create(h
)) == NULL
||
6551 (inst
= scf_instance_create(h
)) == NULL
||
6552 (t
= scf_tmpl_pg_create(h
)) == NULL
) {
6554 * Sets SCF_ERROR_INVALID_ARGUMENT, SCF_ERROR_NO_MEMORY,
6555 * SCF_ERROR_NO_RESOURCES, SCF_ERROR_INTERNAL or
6556 * SCF_ERROR_HANDLE_DESTROYED.
6561 if ((type
= malloc(rsize
)) == NULL
||
6562 (pg_name
= malloc(nsize
)) == NULL
) {
6563 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
6567 if (scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, inst
, NULL
, NULL
,
6568 SCF_DECODE_FMRI_EXACT
|SCF_DECODE_FMRI_REQUIRE_INSTANCE
) != 0) {
6569 if (ismember(scf_error(), errors_server
)) {
6571 } else switch (scf_error()) {
6572 case SCF_ERROR_CONSTRAINT_VIOLATED
:
6573 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6576 case SCF_ERROR_INVALID_ARGUMENT
:
6577 case SCF_ERROR_NOT_FOUND
:
6580 case SCF_ERROR_HANDLE_MISMATCH
:
6581 case SCF_ERROR_NOT_SET
:
6588 if (snapshot
== NULL
|| strcmp(snapshot
, "running") == 0 ||
6589 (flags
& SCF_TMPL_VALIDATE_FLAG_CURRENT
)) {
6590 if (_get_snapshot(inst
, NULL
, &snap
) == -1)
6593 (void) scf_set_error(SCF_ERROR_NONE
);
6594 if (_get_snapshot(inst
, snapshot
, &snap
) == -1) {
6596 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
6600 if (_scf_tmpl_check_pg_redef(h
, fmri
, snapshot
, *errs
) != 0) {
6605 * Check that property groups on this instance conform to the template.
6607 if (scf_iter_instance_pgs_composed(iter
, inst
, snap
) != 0) {
6608 if (ismember(scf_error(), errors_server
)) {
6616 while ((r
= scf_iter_next_pg(iter
, pg
)) == 1) {
6617 if (scf_pg_get_name(pg
, pg_name
, nsize
) == -1) {
6618 if (ismember(scf_error(), errors_server
)) {
6626 if (scf_pg_get_type(pg
, type
, rsize
) == -1) {
6627 if (ismember(scf_error(), errors_server
)) {
6635 if (scf_tmpl_get_by_pg_name(fmri
, snapshot
, pg_name
, type
, t
,
6637 if (ismember(scf_error(), errors_server
)) {
6639 } else switch (scf_error()) {
6640 case SCF_ERROR_NOT_FOUND
:
6643 case SCF_ERROR_INVALID_ARGUMENT
:
6652 if (_check_pg(t
, pg
, pg_name
, type
, *errs
) != 0)
6656 if (ismember(scf_error(), errors_server
)) {
6664 scf_tmpl_pg_reset(t
);
6667 * Confirm required property groups are present.
6669 while ((r
= scf_tmpl_iter_pgs(t
, fmri
, snapshot
, NULL
,
6670 SCF_PG_TMPL_FLAG_REQUIRED
)) == 1) {
6674 if (scf_tmpl_pg_name(t
, &pg_name
) == -1)
6676 if (scf_tmpl_pg_type(t
, &type
) == -1)
6679 * required property group templates should not have
6680 * wildcarded name or type
6682 if (strcmp(pg_name
, SCF_TMPL_WILDCARD
) == 0 ||
6683 strcmp(type
, SCF_TMPL_WILDCARD
) == 0) {
6684 (void) scf_set_error(SCF_ERROR_TEMPLATE_INVALID
);
6688 if (_get_pg(NULL
, inst
, snap
, pg_name
, pg
) != 0) {
6689 if (ismember(scf_error(), errors_server
)) {
6691 } else switch (scf_error()) {
6692 case SCF_ERROR_NOT_FOUND
:
6693 if (_add_tmpl_missing_pg_error(*errs
, t
) == -1)
6697 case SCF_ERROR_INVALID_ARGUMENT
:
6698 case SCF_ERROR_HANDLE_MISMATCH
:
6699 case SCF_ERROR_NOT_SET
:
6707 if (ismember(scf_error(), errors_server
)) {
6709 } else switch (scf_error()) {
6710 case SCF_ERROR_NOT_FOUND
:
6713 case SCF_ERROR_INVALID_ARGUMENT
:
6723 if ((*errs
)->tes_num_errs
> 0)
6727 /* there are no errors to report */
6728 scf_tmpl_errors_destroy(*errs
);
6731 scf_tmpl_pg_destroy(t
);
6735 scf_iter_destroy(iter
);
6737 scf_instance_destroy(inst
);
6738 scf_snapshot_destroy(snap
);
6744 scf_tmpl_errors_destroy(scf_tmpl_errors_t
*errs
)
6747 scf_tmpl_error_t
*e
;
6752 for (i
= 0; i
< errs
->tes_num_errs
; ++i
) {
6753 e
= errs
->tes_errs
[i
];
6754 if (errs
->tes_flag
!= 0) {
6755 free((char *)e
->te_pg_name
);
6756 free((char *)e
->te_prop_name
);
6757 free((char *)e
->te_ev1
);
6758 free((char *)e
->te_ev2
);
6759 free((char *)e
->te_actual
);
6760 free((char *)e
->te_tmpl_fmri
);
6761 free((char *)e
->te_tmpl_pg_name
);
6762 free((char *)e
->te_tmpl_pg_type
);
6763 free((char *)e
->te_tmpl_prop_name
);
6764 free((char *)e
->te_tmpl_prop_type
);
6768 free((char *)errs
->tes_fmri
);
6769 free((char *)errs
->tes_prefix
);
6770 free(errs
->tes_errs
);
6775 scf_tmpl_error_source_fmri(const scf_tmpl_error_t
*err
, char **fmri
)
6777 assert(err
!= NULL
);
6778 switch (err
->te_type
) {
6779 case SCF_TERR_MISSING_PG
:
6780 case SCF_TERR_WRONG_PG_TYPE
:
6781 case SCF_TERR_MISSING_PROP
:
6782 case SCF_TERR_WRONG_PROP_TYPE
:
6783 case SCF_TERR_CARDINALITY_VIOLATION
:
6784 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6785 case SCF_TERR_RANGE_VIOLATION
:
6786 case SCF_TERR_PROP_TYPE_MISMATCH
:
6787 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6788 case SCF_TERR_INVALID_VALUE
:
6789 case SCF_TERR_PG_REDEFINE
:
6790 *fmri
= (char *)err
->te_tmpl_fmri
;
6794 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6800 scf_tmpl_error_type(const scf_tmpl_error_t
*err
, scf_tmpl_error_type_t
*type
)
6802 assert(err
!= NULL
);
6803 switch (err
->te_type
) {
6804 case SCF_TERR_MISSING_PG
:
6805 case SCF_TERR_WRONG_PG_TYPE
:
6806 case SCF_TERR_MISSING_PROP
:
6807 case SCF_TERR_WRONG_PROP_TYPE
:
6808 case SCF_TERR_CARDINALITY_VIOLATION
:
6809 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6810 case SCF_TERR_RANGE_VIOLATION
:
6811 case SCF_TERR_PROP_TYPE_MISMATCH
:
6812 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6813 case SCF_TERR_INVALID_VALUE
:
6814 case SCF_TERR_PG_REDEFINE
:
6815 *type
= err
->te_type
;
6819 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6825 scf_tmpl_error_pg_tmpl(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6827 assert(err
!= NULL
);
6828 switch (err
->te_type
) {
6829 case SCF_TERR_MISSING_PG
:
6830 case SCF_TERR_WRONG_PG_TYPE
:
6831 case SCF_TERR_MISSING_PROP
:
6832 case SCF_TERR_WRONG_PROP_TYPE
:
6833 case SCF_TERR_CARDINALITY_VIOLATION
:
6834 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6835 case SCF_TERR_RANGE_VIOLATION
:
6836 case SCF_TERR_PROP_TYPE_MISMATCH
:
6837 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6838 case SCF_TERR_INVALID_VALUE
:
6839 case SCF_TERR_PG_REDEFINE
:
6840 if (err
->te_tmpl_pg_name
!= NULL
&&
6841 err
->te_tmpl_pg_type
!= NULL
) {
6843 *name
= (char *)err
->te_tmpl_pg_name
;
6845 *type
= (char *)err
->te_tmpl_pg_type
;
6848 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6851 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6857 scf_tmpl_error_pg(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6859 assert(err
!= NULL
);
6860 switch (err
->te_type
) {
6861 case SCF_TERR_WRONG_PG_TYPE
:
6862 if (err
->te_pg_name
!= NULL
&&
6863 err
->te_actual
!= NULL
) {
6865 *name
= (char *)err
->te_pg_name
;
6867 *type
= (char *)err
->te_actual
;
6870 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6872 case SCF_TERR_WRONG_PROP_TYPE
:
6873 case SCF_TERR_CARDINALITY_VIOLATION
:
6874 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6875 case SCF_TERR_RANGE_VIOLATION
:
6876 if (err
->te_pg_name
!= NULL
&&
6877 err
->te_tmpl_pg_type
!= NULL
) {
6879 *name
= (char *)err
->te_pg_name
;
6881 *type
= (char *)err
->te_tmpl_pg_type
;
6885 case SCF_TERR_MISSING_PROP
:
6886 case SCF_TERR_MISSING_PG
:
6887 case SCF_TERR_PROP_TYPE_MISMATCH
:
6888 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6889 case SCF_TERR_INVALID_VALUE
:
6890 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6892 case SCF_TERR_PG_REDEFINE
:
6893 if (err
->te_ev1
!= NULL
&& err
->te_ev2
!= NULL
) {
6895 *name
= (char *)err
->te_ev1
;
6897 *type
= (char *)err
->te_ev2
;
6900 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6903 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6909 scf_tmpl_error_prop_tmpl(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6911 assert(err
!= NULL
);
6912 switch (err
->te_type
) {
6913 case SCF_TERR_MISSING_PROP
:
6914 case SCF_TERR_WRONG_PROP_TYPE
:
6915 case SCF_TERR_CARDINALITY_VIOLATION
:
6916 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6917 case SCF_TERR_RANGE_VIOLATION
:
6918 case SCF_TERR_PROP_TYPE_MISMATCH
:
6919 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6920 case SCF_TERR_INVALID_VALUE
:
6921 if (err
->te_tmpl_prop_name
!= NULL
&&
6922 err
->te_tmpl_prop_type
!= NULL
) {
6924 *name
= (char *)err
->te_tmpl_prop_name
;
6926 *type
= (char *)err
->te_tmpl_prop_type
;
6930 case SCF_TERR_MISSING_PG
:
6931 case SCF_TERR_WRONG_PG_TYPE
:
6932 case SCF_TERR_PG_REDEFINE
:
6933 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6936 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6942 scf_tmpl_error_prop(const scf_tmpl_error_t
*err
, char **name
, char **type
)
6944 assert(err
!= NULL
);
6945 switch (err
->te_type
) {
6946 case SCF_TERR_WRONG_PROP_TYPE
:
6947 case SCF_TERR_CARDINALITY_VIOLATION
:
6948 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6949 case SCF_TERR_RANGE_VIOLATION
:
6950 if (err
->te_prop_name
!= NULL
&&
6951 err
->te_tmpl_prop_type
!= NULL
) {
6953 *name
= (char *)err
->te_prop_name
;
6955 *type
= (char *)err
->te_tmpl_prop_type
;
6959 case SCF_TERR_MISSING_PG
:
6960 case SCF_TERR_WRONG_PG_TYPE
:
6961 case SCF_TERR_MISSING_PROP
:
6962 case SCF_TERR_PROP_TYPE_MISMATCH
:
6963 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6964 case SCF_TERR_INVALID_VALUE
:
6965 case SCF_TERR_PG_REDEFINE
:
6966 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6969 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
6975 scf_tmpl_error_value(const scf_tmpl_error_t
*err
, char **val
)
6977 assert(err
!= NULL
);
6978 switch (err
->te_type
) {
6979 case SCF_TERR_VALUE_CONSTRAINT_VIOLATED
:
6980 case SCF_TERR_RANGE_VIOLATION
:
6981 case SCF_TERR_VALUE_OUT_OF_RANGE
:
6982 case SCF_TERR_INVALID_VALUE
:
6983 if (err
->te_actual
!= NULL
) {
6985 *val
= (char *)err
->te_actual
;
6989 case SCF_TERR_MISSING_PG
:
6990 case SCF_TERR_WRONG_PG_TYPE
:
6991 case SCF_TERR_MISSING_PROP
:
6992 case SCF_TERR_WRONG_PROP_TYPE
:
6993 case SCF_TERR_CARDINALITY_VIOLATION
:
6994 case SCF_TERR_PROP_TYPE_MISMATCH
:
6995 case SCF_TERR_PG_REDEFINE
:
6996 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
6999 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
7005 scf_tmpl_visibility_to_string(uint8_t vis
)
7007 if (vis
== SCF_TMPL_VISIBILITY_READONLY
)
7008 return (SCF_TM_VISIBILITY_READONLY
);
7009 else if (vis
== SCF_TMPL_VISIBILITY_HIDDEN
)
7010 return (SCF_TM_VISIBILITY_HIDDEN
);
7011 else if (vis
== SCF_TMPL_VISIBILITY_READWRITE
)
7012 return (SCF_TM_VISIBILITY_READWRITE
);