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]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include "libscf_impl.h"
32 * Errors returned by smf_notify_{del|get|set}_params()
34 static const scf_error_t errs_1
[] = {
35 SCF_ERROR_BACKEND_ACCESS
,
36 SCF_ERROR_BACKEND_READONLY
,
37 SCF_ERROR_CONNECTION_BROKEN
,
40 SCF_ERROR_INVALID_ARGUMENT
,
42 SCF_ERROR_NO_RESOURCES
,
44 SCF_ERROR_PERMISSION_DENIED
,
49 * Errors returned by smf_notify_{del|get|set}_params()
50 * Except SCF_ERROR_INVALID_ARGUMENT
52 static const scf_error_t errs_2
[] = {
53 SCF_ERROR_BACKEND_ACCESS
,
54 SCF_ERROR_BACKEND_READONLY
,
55 SCF_ERROR_CONNECTION_BROKEN
,
59 SCF_ERROR_NO_RESOURCES
,
61 SCF_ERROR_PERMISSION_DENIED
,
66 * Helper function that abort() on unexpected errors.
67 * The expected error set is a zero-terminated array of scf_error_t
70 check_scf_error(scf_error_t e
, const scf_error_t
*errs
)
72 if (ismember(e
, errs
))
82 * Mapping of state transition to pgname.
84 static struct st_pgname
{
85 const char *st_pgname
;
88 { "to-uninitialized", SCF_TRANS(0, SCF_STATE_UNINIT
) },
89 { "from-uninitialized", SCF_TRANS(SCF_STATE_UNINIT
, 0) },
90 { "to-maintenance", SCF_TRANS(0, SCF_STATE_MAINT
) },
91 { "from-maintenance", SCF_TRANS(SCF_STATE_MAINT
, 0) },
92 { "to-offline", SCF_TRANS(0, SCF_STATE_OFFLINE
) },
93 { "from-offline", SCF_TRANS(SCF_STATE_OFFLINE
, 0) },
94 { "to-disabled", SCF_TRANS(0, SCF_STATE_DISABLED
) },
95 { "from-disabled", SCF_TRANS(SCF_STATE_DISABLED
, 0) },
96 { "to-online", SCF_TRANS(0, SCF_STATE_ONLINE
) },
97 { "from-online", SCF_TRANS(SCF_STATE_ONLINE
, 0) },
98 { "to-degraded", SCF_TRANS(0, SCF_STATE_DEGRADED
) },
99 { "from-degraded", SCF_TRANS(SCF_STATE_DEGRADED
, 0) },
104 * Check if class matches or is a subclass of SCF_SVC_TRANSITION_CLASS
106 * returns 1, otherwise return 0
109 is_svc_stn(const char *class)
111 int n
= strlen(SCF_SVC_TRANSITION_CLASS
);
113 if (class && strncmp(class, SCF_SVC_TRANSITION_CLASS
, n
) == 0)
114 if (class[n
] == '\0' || class[n
] == '.')
120 * Return the len of the base class. For instance, "class.class1.class2.*"
121 * will return the length of "class.class1.class2"
122 * This function does not check if the class or base class is valid.
123 * A class such as "class.class1....****" is not valid but will return the
124 * length of "class.class1....***"
127 base_class_len(const char *c
)
132 if ((n
= strlen(c
)) == 0)
137 /* get rid of any trailing asterisk */
141 /* make sure the class doesn't end in '.' */
142 while (p
>= c
&& *--p
== '.')
149 * Allocates and builds the pgname for an FMA dotted class.
150 * The pgname will be of the form "class.class1.class2,SCF_NOTIFY_PG_POSTFIX"
155 class_to_pgname(const char *class)
158 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
161 n
= base_class_len(class);
164 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
168 if ((pgname
= malloc(sz
)) == NULL
) {
169 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
173 if (snprintf(pgname
, sz
, "%.*s,%s", (int)n
, class,
174 SCF_NOTIFY_PG_POSTFIX
) >= sz
) {
175 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
188 * Get the pg from the running snapshot of the instance (composed or not)
191 get_pg(scf_service_t
*s
, scf_instance_t
*i
, const char *n
,
192 scf_propertygroup_t
*pg
, int composed
)
194 scf_handle_t
*h
= scf_instance_handle(i
);
195 scf_error_t scf_e
= scf_error();
196 scf_snapshot_t
*snap
= scf_snapshot_create(h
);
197 scf_snaplevel_t
*slvl
= scf_snaplevel_create(h
);
202 * Use the error stored in scf_e
204 (void) scf_set_error(scf_e
);
208 if (snap
== NULL
|| slvl
== NULL
)
210 if (scf_instance_get_snapshot(i
, "running", snap
) != 0)
214 if (scf_instance_get_pg_composed(i
, snap
, n
, pg
) != 0)
217 if (scf_snapshot_get_base_snaplevel(snap
, slvl
) != 0 ||
218 scf_snaplevel_get_pg(slvl
, n
, pg
) != 0)
222 if (scf_service_get_pg(s
, n
, pg
) != 0)
228 scf_snaplevel_destroy(slvl
);
229 scf_snapshot_destroy(snap
);
235 * Add a pg if it does not exist, or get it if it exists.
236 * It operates on the instance if the service parameter is NULL.
238 * returns 0 on success or -1 on failure
241 get_or_add_pg(scf_service_t
*s
, scf_instance_t
*i
, const char *n
, const char *t
,
242 uint32_t flags
, scf_propertygroup_t
*pg
)
247 r
= scf_instance_add_pg(i
, n
, t
, flags
, pg
);
249 r
= scf_service_add_pg(s
, n
, t
, flags
, pg
);
253 else if (scf_error() != SCF_ERROR_EXISTS
)
257 r
= scf_instance_get_pg(i
, n
, pg
);
259 r
= scf_service_get_pg(s
, n
, pg
);
265 * Delete the property group form the instance or service.
266 * If service is NULL, use instance, otherwise use only the service.
268 * Return SCF_SUCCESS or SCF_FAILED on
269 * SCF_ERROR_BACKEND_ACCESS
270 * SCF_ERROR_BACKEND_READONLY
271 * SCF_ERROR_CONNECTION_BROKEN
273 * SCF_ERROR_HANDLE_MISMATCH
275 * SCF_ERROR_INVALID_ARGUMENT
276 * SCF_ERROR_NO_RESOURCES
277 * SCF_ERROR_NOT_BOUND
278 * SCF_ERROR_NOT_FOUND
280 * SCF_ERROR_PERMISSION_DENIED
283 del_pg(scf_service_t
*s
, scf_instance_t
*i
, const char *n
,
284 scf_propertygroup_t
*pg
)
286 if ((s
== NULL
? scf_instance_get_pg(i
, n
, pg
) :
287 scf_service_get_pg(s
, n
, pg
)) != SCF_SUCCESS
)
288 if (scf_error() == SCF_ERROR_NOT_FOUND
)
289 return (SCF_SUCCESS
);
293 if (scf_pg_delete(pg
) != SCF_SUCCESS
)
294 if (scf_error() == SCF_ERROR_DELETED
)
295 return (SCF_SUCCESS
);
299 return (SCF_SUCCESS
);
303 get_scf_type(nvpair_t
*p
)
305 switch (nvpair_type(p
)) {
306 case DATA_TYPE_BOOLEAN
:
307 case DATA_TYPE_BOOLEAN_VALUE
:
308 case DATA_TYPE_BOOLEAN_ARRAY
:
309 return (SCF_TYPE_BOOLEAN
);
312 case DATA_TYPE_UINT8
:
313 case DATA_TYPE_UINT16
:
314 case DATA_TYPE_UINT32
:
315 case DATA_TYPE_UINT64
:
316 case DATA_TYPE_BYTE_ARRAY
:
317 case DATA_TYPE_UINT8_ARRAY
:
318 case DATA_TYPE_UINT16_ARRAY
:
319 case DATA_TYPE_UINT32_ARRAY
:
320 case DATA_TYPE_UINT64_ARRAY
:
321 return (SCF_TYPE_COUNT
);
324 case DATA_TYPE_INT16
:
325 case DATA_TYPE_INT32
:
326 case DATA_TYPE_INT64
:
327 case DATA_TYPE_INT8_ARRAY
:
328 case DATA_TYPE_INT16_ARRAY
:
329 case DATA_TYPE_INT32_ARRAY
:
330 case DATA_TYPE_INT64_ARRAY
:
331 return (SCF_TYPE_INTEGER
);
333 case DATA_TYPE_STRING
:
334 case DATA_TYPE_STRING_ARRAY
:
335 return (SCF_TYPE_ASTRING
);
338 return (SCF_TYPE_INVALID
);
343 add_entry(scf_transaction_entry_t
*te
, scf_value_t
*val
)
345 if (scf_entry_add_value(te
, val
) != 0) {
346 scf_value_destroy(val
);
350 return (SCF_SUCCESS
);
354 add_boolean_entry(scf_handle_t
*h
, scf_transaction_entry_t
*te
, uint8_t v
)
356 scf_value_t
*val
= scf_value_create(h
);
361 scf_value_set_boolean(val
, v
);
363 return (add_entry(te
, val
));
367 add_count_entry(scf_handle_t
*h
, scf_transaction_entry_t
*te
, uint64_t v
)
369 scf_value_t
*val
= scf_value_create(h
);
374 scf_value_set_count(val
, v
);
376 return (add_entry(te
, val
));
380 add_integer_entry(scf_handle_t
*h
, scf_transaction_entry_t
*te
, int64_t v
)
382 scf_value_t
*val
= scf_value_create(h
);
387 scf_value_set_integer(val
, v
);
389 return (add_entry(te
, val
));
393 add_astring_entry(scf_handle_t
*h
, scf_transaction_entry_t
*te
, char *s
)
395 scf_value_t
*val
= scf_value_create(h
);
400 if (scf_value_set_astring(val
, s
) != 0) {
401 scf_value_destroy(val
);
405 return (add_entry(te
, val
));
409 get_nvpair_vals(scf_handle_t
*h
, scf_transaction_entry_t
*te
, nvpair_t
*p
)
411 scf_value_t
*val
= scf_value_create(h
);
418 switch (nvpair_type(p
)) {
419 case DATA_TYPE_BOOLEAN
:
420 return (add_boolean_entry(h
, te
, 1));
421 case DATA_TYPE_BOOLEAN_VALUE
:
425 (void) nvpair_value_boolean_value(p
, &v
);
426 return (add_boolean_entry(h
, te
, (uint8_t)v
));
428 case DATA_TYPE_BOOLEAN_ARRAY
:
432 (void) nvpair_value_boolean_array(p
, &v
, &n
);
433 for (i
= 0; i
< n
; ++i
) {
434 if (add_boolean_entry(h
, te
, (uint8_t)v
[i
]) !=
438 return (SCF_SUCCESS
);
444 (void) nvpair_value_byte(p
, &v
);
445 return (add_count_entry(h
, te
, v
));
447 case DATA_TYPE_UINT8
:
451 (void) nvpair_value_uint8(p
, &v
);
452 return (add_count_entry(h
, te
, v
));
454 case DATA_TYPE_UINT16
:
458 (void) nvpair_value_uint16(p
, &v
);
459 return (add_count_entry(h
, te
, v
));
461 case DATA_TYPE_UINT32
:
465 (void) nvpair_value_uint32(p
, &v
);
466 return (add_count_entry(h
, te
, v
));
468 case DATA_TYPE_UINT64
:
472 (void) nvpair_value_uint64(p
, &v
);
473 return (add_count_entry(h
, te
, v
));
475 case DATA_TYPE_BYTE_ARRAY
:
479 (void) nvpair_value_byte_array(p
, &v
, &n
);
480 for (i
= 0; i
< n
; ++i
) {
481 if (add_count_entry(h
, te
, v
[i
]) != SCF_SUCCESS
)
484 return (SCF_SUCCESS
);
486 case DATA_TYPE_UINT8_ARRAY
:
490 (void) nvpair_value_uint8_array(p
, &v
, &n
);
491 for (i
= 0; i
< n
; ++i
) {
492 if (add_count_entry(h
, te
, v
[i
]) != SCF_SUCCESS
)
495 return (SCF_SUCCESS
);
497 case DATA_TYPE_UINT16_ARRAY
:
501 (void) nvpair_value_uint16_array(p
, &v
, &n
);
502 for (i
= 0; i
< n
; ++i
) {
503 if (add_count_entry(h
, te
, v
[i
]) != SCF_SUCCESS
)
506 return (SCF_SUCCESS
);
508 case DATA_TYPE_UINT32_ARRAY
:
512 (void) nvpair_value_uint32_array(p
, &v
, &n
);
513 for (i
= 0; i
< n
; ++i
) {
514 if (add_count_entry(h
, te
, v
[i
]) != SCF_SUCCESS
)
517 return (SCF_SUCCESS
);
519 case DATA_TYPE_UINT64_ARRAY
:
523 (void) nvpair_value_uint64_array(p
, &v
, &n
);
524 for (i
= 0; i
< n
; ++i
) {
525 if (add_count_entry(h
, te
, v
[i
]) != SCF_SUCCESS
)
528 return (SCF_SUCCESS
);
534 (void) nvpair_value_int8(p
, &v
);
535 return (add_integer_entry(h
, te
, v
));
537 case DATA_TYPE_INT16
:
541 (void) nvpair_value_int16(p
, &v
);
542 return (add_integer_entry(h
, te
, v
));
544 case DATA_TYPE_INT32
:
548 (void) nvpair_value_int32(p
, &v
);
549 return (add_integer_entry(h
, te
, v
));
551 case DATA_TYPE_INT64
:
555 (void) nvpair_value_int64(p
, &v
);
556 return (add_integer_entry(h
, te
, v
));
558 case DATA_TYPE_INT8_ARRAY
:
562 (void) nvpair_value_int8_array(p
, &v
, &n
);
563 for (i
= 0; i
< n
; ++i
) {
564 if (add_integer_entry(h
, te
, v
[i
]) !=
568 return (SCF_SUCCESS
);
570 case DATA_TYPE_INT16_ARRAY
:
574 (void) nvpair_value_int16_array(p
, &v
, &n
);
575 for (i
= 0; i
< n
; ++i
) {
576 if (add_integer_entry(h
, te
, v
[i
]) !=
580 return (SCF_SUCCESS
);
582 case DATA_TYPE_INT32_ARRAY
:
586 (void) nvpair_value_int32_array(p
, &v
, &n
);
587 for (i
= 0; i
< n
; ++i
) {
588 if (add_integer_entry(h
, te
, v
[i
]) !=
592 return (SCF_SUCCESS
);
594 case DATA_TYPE_INT64_ARRAY
:
598 (void) nvpair_value_int64_array(p
, &v
, &n
);
599 for (i
= 0; i
< n
; ++i
) {
600 if (add_integer_entry(h
, te
, v
[i
]) !=
604 return (SCF_SUCCESS
);
606 case DATA_TYPE_STRING
:
610 (void) nvpair_value_string(p
, &str
);
611 return (add_astring_entry(h
, te
, str
));
613 case DATA_TYPE_STRING_ARRAY
:
617 (void) nvpair_value_string_array(p
, &v
, &n
);
618 for (i
= 0; i
< n
; ++i
) {
619 if (add_astring_entry(h
, te
, v
[i
]) !=
623 return (SCF_SUCCESS
);
626 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
634 * Add new transaction entry to scf_transaction_t
637 * SCF_ERROR_BACKEND_ACCESS
638 * SCF_ERROR_CONNECTION_BROKEN
641 * SCF_ERROR_NO_RESOURCES
642 * SCF_ERROR_NOT_FOUND
645 prep_transaction(scf_transaction_t
*tx
, scf_transaction_entry_t
*te
,
646 const char *prop
, scf_type_t type
)
648 if (scf_transaction_property_new(tx
, te
, prop
, type
) != SCF_SUCCESS
&&
649 (scf_error() != SCF_ERROR_EXISTS
||
650 scf_transaction_property_change(tx
, te
, prop
, type
) !=
652 if (check_scf_error(scf_error(), errs_2
)) {
657 return (SCF_SUCCESS
);
661 * notify_set_params()
662 * returns 0 on success or -1 on failure
663 * SCF_ERROR_BACKEND_ACCESS
664 * SCF_ERROR_BACKEND_READONLY
665 * SCF_ERROR_CONNECTION_BROKEN
668 * SCF_ERROR_INVALID_ARGUMENT
669 * SCF_ERROR_NO_MEMORY
670 * SCF_ERROR_NO_RESOURCES
671 * SCF_ERROR_NOT_FOUND
672 * SCF_ERROR_PERMISSION_DENIED
675 notify_set_params(scf_propertygroup_t
*pg
, nvlist_t
*params
)
677 scf_handle_t
*h
= scf_pg_handle(pg
);
678 scf_error_t scf_e
= scf_error();
679 scf_transaction_t
*tx
= scf_transaction_create(h
);
680 int bufsz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
681 char *propname
= malloc(bufsz
);
687 * Use the error stored in scf_e
689 (void) scf_set_error(scf_e
);
695 if (propname
== NULL
) {
696 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
704 * make sure we have the most recent version of the pg
705 * start the transaction
707 if (scf_pg_update(pg
) == SCF_FAILED
||
708 scf_transaction_start(tx
, pg
) != SCF_SUCCESS
) {
709 if (check_scf_error(scf_error(), errs_2
)) {
714 for (nvp
= nvlist_next_nvpair(params
, NULL
); nvp
!= NULL
;
715 nvp
= nvlist_next_nvpair(params
, nvp
)) {
719 /* we ONLY take nvlists here */
720 if (nvpair_type(nvp
) != DATA_TYPE_NVLIST
) {
721 char *name
= nvpair_name(nvp
);
724 * if this is output from
725 * smf_notify_get_params() we want to skip
726 * the tset value of the nvlist
728 if (strcmp(name
, SCF_NOTIFY_NAME_TSET
) == 0)
731 (void) scf_set_error(
732 SCF_ERROR_INVALID_ARGUMENT
);
736 if (nvpair_value_nvlist(nvp
, &m
) != 0) {
737 (void) scf_set_error(
738 SCF_ERROR_INVALID_ARGUMENT
);
743 * Traverse each mechanism list
745 for (p
= nvlist_next_nvpair(m
, NULL
); p
!= NULL
;
746 p
= nvlist_next_nvpair(m
, p
)) {
747 scf_transaction_entry_t
*te
=
749 /* map the nvpair type to scf type */
750 scf_type_t type
= get_scf_type(p
);
754 SCF_ERROR_INVALID_ARGUMENT
) {
755 scf_entry_destroy(te
);
763 if (type
== SCF_TYPE_INVALID
) {
764 (void) scf_set_error(
765 SCF_ERROR_INVALID_ARGUMENT
);
766 scf_entry_destroy(te
);
770 if (snprintf(propname
, bufsz
, "%s,%s",
771 nvpair_name(nvp
), nvpair_name(p
)) >=
773 (void) scf_set_error(
774 SCF_ERROR_INVALID_ARGUMENT
);
775 scf_entry_destroy(te
);
779 if (prep_transaction(tx
, te
, propname
, type
) !=
781 scf_entry_destroy(te
);
785 if (get_nvpair_vals(h
, te
, p
) != SCF_SUCCESS
) {
786 if (check_scf_error(scf_error(),
793 err
= scf_transaction_commit(tx
);
794 scf_transaction_destroy_children(tx
);
798 if (check_scf_error(scf_error(), errs_2
)) {
806 scf_transaction_destroy_children(tx
);
807 scf_transaction_destroy(tx
);
814 * Decode fmri. Populates service OR instance depending on which one is an
815 * exact match to the fmri parameter.
817 * The function destroys and sets the unused entity (service or instance) to
820 * return SCF_SUCCESS or SCF_FAILED on
821 * SCF_ERROR_BACKEND_ACCESS
822 * SCF_ERROR_CONNECTION_BROKEN
823 * SCF_ERROR_CONSTRAINT_VIOLATED
825 * SCF_ERROR_HANDLE_MISMATCH
827 * SCF_ERROR_INVALID_ARGUMENT
828 * SCF_ERROR_NO_RESOURCES
829 * SCF_ERROR_NOT_BOUND
830 * SCF_ERROR_NOT_FOUND
834 decode_fmri(const char *fmri
, scf_handle_t
*h
, scf_service_t
**s
,
837 if (scf_handle_decode_fmri(h
, fmri
, NULL
, *s
, NULL
, NULL
, NULL
,
838 SCF_DECODE_FMRI_EXACT
) != SCF_SUCCESS
) {
839 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
840 scf_service_destroy(*s
);
847 if (scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, *i
,
848 NULL
, NULL
, SCF_DECODE_FMRI_EXACT
) != SCF_SUCCESS
) {
852 return (SCF_SUCCESS
);
856 * Return size in bytes for an SCF_TYPE_*. Not all libscf types are supported
859 get_type_size(scf_type_t t
)
862 case SCF_TYPE_BOOLEAN
:
863 return (sizeof (uint8_t));
865 return (sizeof (uint64_t));
866 case SCF_TYPE_INTEGER
:
867 return (sizeof (int64_t));
868 case SCF_TYPE_ASTRING
:
869 case SCF_TYPE_USTRING
:
870 return (sizeof (void *));
879 * Return a pointer to the array of values according to its type
882 get_v_pointer(scf_values_t
*v
)
884 switch (v
->value_type
) {
885 case SCF_TYPE_BOOLEAN
:
886 return ((void **)&v
->values
.v_boolean
);
888 return ((void **)&v
->values
.v_count
);
889 case SCF_TYPE_INTEGER
:
890 return ((void **)&v
->values
.v_integer
);
891 case SCF_TYPE_ASTRING
:
892 return ((void **)&v
->values
.v_astring
);
893 case SCF_TYPE_USTRING
:
894 return ((void **)&v
->values
.v_ustring
);
903 * Populate scf_values_t value array at position c.
906 get_value(scf_value_t
*val
, scf_values_t
*v
, int c
, char *buf
, int sz
)
908 switch (v
->value_type
) {
909 case SCF_TYPE_BOOLEAN
:
910 return (scf_value_get_boolean(val
, v
->values
.v_boolean
+ c
));
912 return (scf_value_get_count(val
, v
->values
.v_count
+ c
));
913 case SCF_TYPE_INTEGER
:
914 return (scf_value_get_integer(val
, v
->values
.v_integer
+ c
));
915 case SCF_TYPE_ASTRING
:
916 if (scf_value_get_astring(val
, buf
, sz
) < 0 ||
917 (v
->values
.v_astring
[c
] = strdup(buf
)) == NULL
) {
918 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
922 case SCF_TYPE_USTRING
:
923 if (scf_value_get_ustring(val
, buf
, sz
) < 0 ||
924 (v
->values
.v_ustring
[c
] = strdup(buf
)) == NULL
) {
925 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
937 * Populate scf_values_t structure with values from prop
940 values_get(scf_property_t
*prop
, scf_values_t
*v
)
942 scf_handle_t
*h
= scf_property_handle(prop
);
943 scf_error_t scf_e
= scf_error();
944 scf_value_t
*val
= scf_value_create(h
);
945 scf_iter_t
*it
= scf_iter_create(h
);
946 scf_type_t type
= SCF_TYPE_INVALID
;
947 ssize_t sz
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
) + 1;
948 char *buf
= malloc(sz
);
950 int err
, elem_sz
, count
, cursz
;
954 assert(v
->reserved
== NULL
);
956 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
961 * Use the error stored in scf_e
963 (void) scf_set_error(scf_e
);
966 if (val
== NULL
|| it
== NULL
)
969 if (scf_property_type(prop
, &type
) != SCF_SUCCESS
)
971 if (scf_property_is_type(prop
, v
->value_type
) != SCF_SUCCESS
)
974 elem_sz
= get_type_size(type
);
977 p
= get_v_pointer(v
);
980 cursz
= count
= v
->value_count
;
981 if (scf_iter_property_values(it
, prop
) != 0) {
985 while ((err
= scf_iter_next_value(it
, val
)) == 1) {
986 if (count
+ 1 >= cursz
) {
989 /* set initial size or double it */
990 cursz
= cursz
? 2 * cursz
: 8;
991 if ((tmp
= reallocarray(*p
, cursz
, elem_sz
)) == NULL
) {
992 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
998 if (get_value(val
, v
, count
, buf
, sz
) != 0)
1004 v
->value_count
= count
;
1013 v
->value_count
= count
;
1014 scf_values_destroy(v
);
1018 scf_iter_destroy(it
);
1019 scf_value_destroy(val
);
1024 * Add values from property p to existing nvlist_t nvl. The data type in the
1025 * nvlist is inferred from the scf_type_t of the property.
1027 * Returns SCF_SUCCESS or SCF_FAILED on
1028 * SCF_ERROR_CONNECTION_BROKEN
1030 * SCF_ERROR_HANDLE_DESTROYED
1031 * SCF_ERROR_HANDLE_MISMATCH
1032 * SCF_ERROR_INVALID_ARGUMENT
1033 * SCF_ERROR_NO_MEMORY
1034 * SCF_ERROR_NO_RESOURCES
1035 * SCF_ERROR_NOT_BOUND
1037 * SCF_ERROR_PERMISSION_DENIED
1038 * SCF_ERROR_TYPE_MISMATCH
1041 add_prop_to_nvlist(scf_property_t
*p
, const char *pname
, nvlist_t
*nvl
,
1044 scf_values_t vals
= { 0 };
1045 scf_type_t type
, base_type
;
1049 if (p
== NULL
|| pname
== NULL
|| *pname
== '\0' || nvl
== NULL
) {
1050 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1054 if (scf_property_type(p
, &type
) != 0)
1058 * scf_values_t does not support subtypes of SCF_TYPE_USTRING,
1059 * mapping them all to SCF_TYPE_USTRING
1061 base_type
= scf_true_base_type(type
);
1062 if (base_type
== SCF_TYPE_ASTRING
&& type
!= SCF_TYPE_ASTRING
)
1063 type
= SCF_TYPE_USTRING
;
1065 vals
.value_type
= type
;
1066 if (values_get(p
, &vals
) != SCF_SUCCESS
) {
1067 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT
) {
1074 switch (vals
.value_type
) {
1075 case SCF_TYPE_BOOLEAN
:
1079 int n
= vals
.value_count
;
1081 v
= calloc(n
, sizeof (boolean_t
));
1083 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1086 for (i
= 0; i
< n
; ++i
)
1087 v
[i
] = (boolean_t
)vals
.values
.v_boolean
[i
];
1089 if (n
== 1 && !array
)
1090 err
= nvlist_add_boolean_value(nvl
, pname
, *v
);
1092 err
= nvlist_add_boolean_array(nvl
, pname
,
1102 case SCF_TYPE_COUNT
:
1103 if (vals
.value_count
== 1 && !array
)
1104 err
= nvlist_add_uint64(nvl
, pname
,
1105 *vals
.values
.v_count
);
1107 err
= nvlist_add_uint64_array(nvl
, pname
,
1108 vals
.values
.v_count
, vals
.value_count
);
1114 case SCF_TYPE_INTEGER
:
1115 if (vals
.value_count
== 1 && !array
)
1116 err
= nvlist_add_int64(nvl
, pname
,
1117 *vals
.values
.v_integer
);
1119 err
= nvlist_add_int64_array(nvl
, pname
,
1120 vals
.values
.v_integer
, vals
.value_count
);
1126 case SCF_TYPE_ASTRING
:
1127 if (vals
.value_count
== 1 && !array
)
1128 err
= nvlist_add_string(nvl
, pname
,
1129 *vals
.values
.v_astring
);
1131 err
= nvlist_add_string_array(nvl
, pname
,
1132 vals
.values
.v_astring
, vals
.value_count
);
1138 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1144 scf_values_destroy(&vals
);
1149 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1152 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1155 /* we should *never* get here */
1163 * Parse property name "mechanism,parameter" into separate mechanism
1164 * and parameter. *mech must be freed by caller. *val points into
1165 * *mech and must not be freed.
1167 * Returns SCF_SUCCESS or SCF_FAILED on
1168 * SCF_ERROR_NO_MEMORY
1169 * SCF_ERROR_NOT_FOUND
1172 get_mech_name(const char *name
, char **mech
, char **val
)
1177 if ((m
= strdup(name
)) == NULL
) {
1178 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1179 return (SCF_FAILED
);
1181 if ((p
= strchr(m
, ',')) == NULL
) {
1183 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
1184 return (SCF_FAILED
);
1190 return (SCF_SUCCESS
);
1194 * Return the number of transitions in a transition set.
1195 * If the transition set is invalid, it returns zero.
1198 num_of_transitions(int32_t t
)
1203 if (SCF_TRANS_VALID(t
)) {
1204 for (i
= 0x1; i
< SCF_STATE_ALL
; i
<<= 1) {
1207 if (SCF_TRANS_INITIAL_STATE(t
) & i
)
1216 * Return the SCF_STATE_* macro value for the state in the FMA classes for
1217 * SMF state transitions. They are of type:
1218 * SCF_SVC_TRANSITION_CLASS.<state>
1219 * ireport.os.smf.state-transition.<state>
1222 class_to_transition(const char *c
)
1228 if (!is_svc_stn(c
)) {
1233 * if we get here, c is SCF_SVC_TRANSITION_CLASS or longer
1235 p
= c
+ strlen(SCF_SVC_TRANSITION_CLASS
);
1241 if ((n
= base_class_len(p
)) == 0)
1244 if ((r
= state_from_string(p
, n
)) == -1)
1251 * return SCF_SUCCESS or SCF_FAILED on
1252 * SCF_ERROR_BACKEND_ACCESS
1253 * SCF_ERROR_BACKEND_READONLY
1254 * SCF_ERROR_CONNECTION_BROKEN
1256 * SCF_ERROR_INTERNAL
1257 * SCF_ERROR_INVALID_ARGUMENT
1258 * SCF_ERROR_NO_MEMORY
1259 * SCF_ERROR_NO_RESOURCES
1260 * SCF_ERROR_NOT_FOUND
1261 * SCF_ERROR_PERMISSION_DENIED
1264 smf_notify_set_params(const char *class, nvlist_t
*attr
)
1268 scf_handle_t
*h
= _scf_handle_create_and_bind(SCF_VERSION
);
1269 scf_error_t scf_e
= scf_error();
1270 scf_service_t
*s
= scf_service_create(h
);
1271 scf_instance_t
*i
= scf_instance_create(h
);
1272 scf_propertygroup_t
*pg
= scf_pg_create(h
);
1273 nvlist_t
*params
= NULL
;
1274 char *fmri
= (char *)SCF_NOTIFY_PARAMS_INST
;
1275 char *pgname
= NULL
;
1280 assert(class != NULL
);
1283 * use saved error if _scf_handle_create_and_bind() fails
1285 (void) scf_set_error(scf_e
);
1288 if (i
== NULL
|| s
== NULL
|| pg
== NULL
)
1292 if (nvlist_lookup_uint32(attr
, SCF_NOTIFY_NAME_VERSION
, &ver
) != 0 ||
1293 ver
!= SCF_NOTIFY_PARAMS_VERSION
) {
1294 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1298 if (nvlist_lookup_nvlist(attr
, SCF_NOTIFY_PARAMS
, ¶ms
) != 0) {
1299 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1303 is_stn
= is_svc_stn(class);
1304 /* special case SMF state transition notification */
1306 (nvlist_lookup_string(attr
, SCF_NOTIFY_NAME_FMRI
, &fmri
) != 0 ||
1307 nvlist_lookup_int32(attr
, SCF_NOTIFY_NAME_TSET
, &tset
) != 0 ||
1308 !SCF_TRANS_VALID(tset
))) {
1309 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1312 if (decode_fmri(fmri
, h
, &s
, &i
) != SCF_SUCCESS
)
1313 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
1314 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1315 } else if (check_scf_error(scf_error(), errs_1
)) {
1320 tset
|= class_to_transition(class);
1322 if (!SCF_TRANS_VALID(tset
)) {
1323 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1327 for (j
= 0; st_pgnames
[j
].st_pgname
!= NULL
; ++j
) {
1328 /* if this transition is not in the tset, continue */
1329 if (!(tset
& st_pgnames
[j
].st_state
))
1332 if (get_or_add_pg(s
, i
, st_pgnames
[j
].st_pgname
,
1333 SCF_NOTIFY_PARAMS_PG_TYPE
, 0, pg
) != 0 &&
1334 check_scf_error(scf_error(), errs_2
))
1337 if (notify_set_params(pg
, params
) != 0)
1341 /* We only need to refresh the instance */
1342 if (_smf_refresh_instance_i(i
) != 0 &&
1343 check_scf_error(scf_error(), errs_1
))
1346 /* We have to refresh all instances in the service */
1347 if (_smf_refresh_all_instances(s
) != 0 &&
1348 check_scf_error(scf_error(), errs_1
))
1352 if ((pgname
= class_to_pgname(class)) == NULL
)
1354 if (get_or_add_pg(s
, i
, pgname
, SCF_GROUP_APPLICATION
, 0, pg
) !=
1356 if (check_scf_error(scf_error(), errs_2
)) {
1360 if (notify_set_params(pg
, params
) != 0) {
1363 if (_smf_refresh_instance_i(i
) != 0 &&
1364 check_scf_error(scf_error(), errs_1
))
1370 scf_instance_destroy(i
);
1371 scf_service_destroy(s
);
1373 scf_handle_destroy(h
);
1380 * returns SCF_SUCCESS or SCF_FAILED on
1381 * SCF_ERROR_CONNECTION_BROKEN
1383 * SCF_ERROR_HANDLE_DESTROYED
1384 * SCF_ERROR_HANDLE_MISMATCH
1385 * SCF_ERROR_INVALID_ARGUMENT
1386 * SCF_ERROR_NO_MEMORY
1387 * SCF_ERROR_NO_RESOURCES
1388 * SCF_ERROR_NOT_BOUND
1389 * SCF_ERROR_NOT_FOUND
1391 * SCF_ERROR_PERMISSION_DENIED
1394 _scf_notify_get_params(scf_propertygroup_t
*pg
, nvlist_t
*params
)
1396 scf_handle_t
*h
= scf_pg_handle(pg
);
1397 scf_error_t scf_e
= scf_error();
1398 scf_property_t
*p
= scf_property_create(h
);
1399 scf_iter_t
*it
= scf_iter_create(h
);
1400 int sz
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
) + 1;
1401 char *name
= malloc(sz
);
1407 * Use the error stored in scf_e
1409 (void) scf_set_error(scf_e
);
1412 if (it
== NULL
|| p
== NULL
)
1416 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1420 if (scf_iter_pg_properties(it
, pg
) != SCF_SUCCESS
) {
1421 if (check_scf_error(scf_error(), errs_1
)) {
1426 while ((err
= scf_iter_next_property(it
, p
)) == 1) {
1432 if (scf_property_get_name(p
, name
, sz
) == SCF_FAILED
) {
1433 if (check_scf_error(scf_error(), errs_1
)) {
1438 if (get_mech_name(name
, &mech
, &val
) != SCF_SUCCESS
) {
1439 if (scf_error() == SCF_ERROR_NOT_FOUND
)
1444 if (nvlist_lookup_nvlist(params
, mech
, &nvl
) != 0) {
1445 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0) != 0) {
1446 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1453 if (add_prop_to_nvlist(p
, val
, nvl
, 1) != SCF_SUCCESS
) {
1454 if (check_scf_error(scf_error(), errs_2
)) {
1461 if (nvlist_add_nvlist(params
, mech
, nvl
) != 0) {
1462 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1475 } else if (check_scf_error(scf_error(), errs_2
)) {
1480 scf_iter_destroy(it
);
1481 scf_property_destroy(p
);
1488 * Look up pg containing an SMF state transition parameters. If it cannot find
1489 * the pg in the composed view of the instance, it will look in the global
1490 * instance for the system wide parameters.
1491 * Instance, service and global instance have to be passed by caller.
1493 * returns SCF_SUCCESS or SCF_FAILED on
1494 * SCF_ERROR_BACKEND_ACCESS
1495 * SCF_ERROR_CONNECTION_BROKEN
1497 * SCF_ERROR_HANDLE_DESTROYED
1498 * SCF_ERROR_HANDLE_MISMATCH
1499 * SCF_ERROR_INTERNAL
1500 * SCF_ERROR_INVALID_ARGUMENT
1501 * SCF_ERROR_NO_MEMORY
1502 * SCF_ERROR_NO_RESOURCES
1503 * SCF_ERROR_NOT_BOUND
1504 * SCF_ERROR_NOT_FOUND
1508 get_stn_pg(scf_service_t
*s
, scf_instance_t
*i
, scf_instance_t
*g
,
1509 const char *pgname
, scf_propertygroup_t
*pg
)
1511 if (get_pg(s
, i
, pgname
, pg
, 1) == 0 ||
1512 scf_error() == SCF_ERROR_NOT_FOUND
&&
1513 get_pg(NULL
, g
, pgname
, pg
, 0) == 0)
1514 return (SCF_SUCCESS
);
1516 return (SCF_FAILED
);
1520 * Populates nvlist_t params with the source fmri for the pg
1522 * return SCF_SUCCESS or SCF_FAILED on
1524 * SCF_ERROR_CONNECTION_BROKEN
1525 * SCF_ERROR_NO_MEMORY
1528 get_pg_source(scf_propertygroup_t
*pg
, nvlist_t
*params
)
1530 size_t sz
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
) + 1;
1531 char *fmri
= malloc(sz
);
1536 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1540 if (scf_pg_to_fmri(pg
, fmri
, sz
) == -1) {
1541 if (check_scf_error(scf_error(), errs_1
)) {
1546 /* get rid of the properties part of the pg source */
1547 if ((p
= strrchr(fmri
, ':')) != NULL
&& p
> fmri
)
1549 if (nvlist_add_string(params
, SCF_NOTIFY_PARAMS_SOURCE_NAME
, fmri
) !=
1551 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1562 * Specialized function to get SMF state transition notification parameters
1564 * return SCF_SUCCESS or SCF_FAILED on
1565 * SCF_ERROR_BACKEND_ACCESS
1566 * SCF_ERROR_CONNECTION_BROKEN
1568 * SCF_ERROR_INTERNAL
1569 * SCF_ERROR_INVALID_ARGUMENT
1570 * SCF_ERROR_NO_MEMORY
1571 * SCF_ERROR_NO_RESOURCES
1572 * SCF_ERROR_NOT_FOUND
1573 * SCF_ERROR_PERMISSION_DENIED
1576 _scf_get_svc_notify_params(const char *fmri
, nvlist_t
*nvl
, int32_t tset
,
1577 int getsource
, int getglobal
)
1579 scf_handle_t
*h
= _scf_handle_create_and_bind(SCF_VERSION
);
1580 scf_error_t scf_e
= scf_error();
1581 scf_service_t
*s
= scf_service_create(h
);
1582 scf_instance_t
*i
= scf_instance_create(h
);
1583 scf_instance_t
*g
= scf_instance_create(h
);
1584 scf_propertygroup_t
*pg
= scf_pg_create(h
);
1586 nvlist_t
**params
= NULL
;
1587 uint_t c
, nvl_num
= 0;
1592 assert(fmri
!= NULL
&& nvl
!= NULL
);
1595 * use saved error if _scf_handle_create_and_bind() fails
1597 (void) scf_set_error(scf_e
);
1600 if (s
== NULL
|| i
== NULL
|| g
== NULL
|| pg
== NULL
)
1603 if (decode_fmri(fmri
, h
, &s
, &i
) != SCF_SUCCESS
||
1604 scf_handle_decode_fmri(h
, SCF_INSTANCE_GLOBAL
, NULL
, NULL
, g
, NULL
,
1605 NULL
, SCF_DECODE_FMRI_EXACT
) != 0) {
1606 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
) {
1607 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1608 } else if (check_scf_error(scf_error(), errs_1
)) {
1613 nvl_num
= num_of_transitions(tset
);
1614 if ((params
= calloc(nvl_num
, sizeof (nvlist_t
*))) == NULL
) {
1615 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1619 for (c
= 0; c
< nvl_num
; ++c
)
1620 if (nvlist_alloc(params
+ c
, NV_UNIQUE_NAME
, 0) != 0) {
1621 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1625 for (c
= 0, j
= 0; st_pgnames
[j
].st_pgname
!= NULL
; ++j
) {
1626 /* if this transition is not in the tset, continue */
1627 if (!(tset
& st_pgnames
[j
].st_state
))
1630 assert(c
< nvl_num
);
1631 pgname
= st_pgnames
[j
].st_pgname
;
1633 if (nvlist_add_int32(params
[c
], SCF_NOTIFY_NAME_TSET
,
1634 st_pgnames
[j
].st_state
) != 0) {
1635 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1638 if ((getglobal
? get_stn_pg(s
, i
, g
, pgname
, pg
) :
1639 get_pg(s
, i
, pgname
, pg
, 1)) == SCF_SUCCESS
) {
1641 if (_scf_notify_get_params(pg
, params
[c
]) !=
1644 if (getsource
&& get_pg_source(pg
, params
[c
]) !=
1647 } else if (scf_error() == SCF_ERROR_NOT_FOUND
||
1648 scf_error() == SCF_ERROR_DELETED
) {
1651 } else if (check_scf_error(scf_error(), errs_1
)) {
1658 (void) scf_set_error(SCF_ERROR_NOT_FOUND
);
1662 assert(c
== nvl_num
);
1664 if (nvlist_add_nvlist_array(nvl
, SCF_NOTIFY_PARAMS
, params
, nvl_num
) !=
1665 0 || nvlist_add_uint32(nvl
, SCF_NOTIFY_NAME_VERSION
,
1666 SCF_NOTIFY_PARAMS_VERSION
) != 0) {
1667 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1675 scf_instance_destroy(i
);
1676 scf_instance_destroy(g
);
1677 scf_service_destroy(s
);
1678 scf_handle_destroy(h
);
1680 for (c
= 0; c
< nvl_num
; ++c
)
1681 nvlist_free(params
[c
]);
1688 * Specialized function to get fma notification parameters
1690 * return SCF_SUCCESS or SCF_FAILED on
1691 * SCF_ERROR_BACKEND_ACCESS
1692 * SCF_ERROR_CONNECTION_BROKEN
1694 * SCF_ERROR_INTERNAL
1695 * SCF_ERROR_INVALID_ARGUMENT
1696 * SCF_ERROR_NO_MEMORY
1697 * SCF_ERROR_NO_RESOURCES
1698 * SCF_ERROR_NOT_FOUND
1699 * SCF_ERROR_PERMISSION_DENIED
1702 _scf_get_fma_notify_params(const char *class, nvlist_t
*nvl
, int getsource
)
1704 scf_handle_t
*h
= _scf_handle_create_and_bind(SCF_VERSION
);
1705 scf_error_t scf_e
= scf_error();
1706 scf_instance_t
*i
= scf_instance_create(h
);
1707 scf_propertygroup_t
*pg
= scf_pg_create(h
);
1709 nvlist_t
*params
= NULL
;
1710 char *pgname
= NULL
;
1714 * use saved error if _scf_handle_create_and_bind() fails
1716 (void) scf_set_error(scf_e
);
1719 if (i
== NULL
|| pg
== NULL
)
1722 if (scf_handle_decode_fmri(h
, SCF_NOTIFY_PARAMS_INST
, NULL
, NULL
, i
,
1723 NULL
, NULL
, SCF_DECODE_FMRI_EXACT
) != SCF_SUCCESS
) {
1724 if (check_scf_error(scf_error(), errs_1
)) {
1729 if ((pgname
= class_to_pgname(class)) == NULL
)
1732 while (get_pg(NULL
, i
, pgname
, pg
, 0) != 0) {
1733 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
1734 char *p
= strrchr(pgname
, '.');
1739 * since the resulting string is shorter,
1740 * there is no risk of buffer overflow
1742 (void) strcpy(p
+ 1, SCF_NOTIFY_PG_POSTFIX
);
1747 if (check_scf_error(scf_error(), errs_1
)) {
1752 if (nvlist_alloc(¶ms
, NV_UNIQUE_NAME
, 0) != 0) {
1753 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1757 if (_scf_notify_get_params(pg
, params
) != SCF_SUCCESS
)
1760 if (getsource
&& get_pg_source(pg
, params
) != SCF_SUCCESS
)
1763 if (nvlist_add_nvlist_array(nvl
, SCF_NOTIFY_PARAMS
, ¶ms
, 1) != 0 ||
1764 nvlist_add_uint32(nvl
, SCF_NOTIFY_NAME_VERSION
,
1765 SCF_NOTIFY_PARAMS_VERSION
) != 0) {
1766 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1773 nvlist_free(params
);
1775 scf_instance_destroy(i
);
1776 scf_handle_destroy(h
);
1783 * Retrieve the notification parameters for the Event described in the
1784 * input nvlist_t nvl.
1785 * The function will allocate an nvlist_t to store the notification
1786 * parameters. The notification parameters in the output nvlist will have
1787 * the following format:
1789 * version (uint32_t)
1790 * SCF_NOTIFY_PARAMS (array of embedded nvlists)
1791 * (start of notify-params[0])
1793 * <mechanism-name> (embedded nvlist)
1794 * <parameter-name> <parameter-type>
1796 * (end <mechanism-name>)
1798 * (end of notify-params[0])
1801 * return SCF_SUCCESS or SCF_FAILED on
1802 * SCF_ERROR_BACKEND_ACCESS
1803 * SCF_ERROR_CONNECTION_BROKEN
1805 * SCF_ERROR_INTERNAL
1806 * SCF_ERROR_INVALID_ARGUMENT
1807 * SCF_ERROR_NO_MEMORY
1808 * SCF_ERROR_NO_RESOURCES
1809 * SCF_ERROR_NOT_FOUND
1810 * SCF_ERROR_PERMISSION_DENIED
1813 smf_notify_get_params(nvlist_t
**params
, nvlist_t
*nvl
)
1816 char *from
; /* from state */
1817 char *to
; /* to state */
1823 if (params
== NULL
|| nvlist_lookup_string(nvl
, "class", &class) != 0) {
1824 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1827 if (nvlist_alloc(params
, NV_UNIQUE_NAME
, 0) != 0) {
1828 (void) scf_set_error(SCF_ERROR_NO_MEMORY
);
1832 if (is_svc_stn(class)) {
1833 if (nvlist_lookup_nvlist(nvl
, "attr", &attr
) != 0 ||
1834 nvlist_lookup_string(attr
, "svc-string", &fmri
) != 0 ||
1835 nvlist_lookup_string(attr
, "from-state", &from
) != 0 ||
1836 nvlist_lookup_string(attr
, "to-state", &to
) != 0) {
1837 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1841 tset
= SCF_TRANS(smf_state_from_string(from
),
1842 smf_state_from_string(to
));
1843 if (!SCF_TRANS_VALID(tset
)) {
1844 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1847 tset
|= class_to_transition(class);
1849 r
= _scf_get_svc_notify_params(fmri
, *params
, tset
, 0, 1);
1851 r
= _scf_get_fma_notify_params(class, *params
, 0);
1855 if (r
== SCF_FAILED
) {
1856 nvlist_free(*params
);
1864 * return SCF_SUCCESS or SCF_FAILED on
1865 * SCF_ERROR_BACKEND_ACCESS
1866 * SCF_ERROR_BACKEND_READONLY
1867 * SCF_ERROR_CONNECTION_BROKEN
1869 * SCF_ERROR_INTERNAL
1870 * SCF_ERROR_INVALID_ARGUMENT
1871 * SCF_ERROR_NO_MEMORY
1872 * SCF_ERROR_NO_RESOURCES
1873 * SCF_ERROR_NOT_FOUND
1874 * SCF_ERROR_PERMISSION_DENIED
1877 smf_notify_del_params(const char *class, const char *fmri
, int32_t tset
)
1879 scf_handle_t
*h
= _scf_handle_create_and_bind(SCF_VERSION
);
1880 scf_error_t scf_e
= scf_error();
1881 scf_service_t
*s
= scf_service_create(h
);
1882 scf_instance_t
*i
= scf_instance_create(h
);
1883 scf_propertygroup_t
*pg
= scf_pg_create(h
);
1885 char *pgname
= NULL
;
1888 if (class == NULL
) {
1889 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1895 * use saved error if _scf_handle_create_and_bind() fails
1897 (void) scf_set_error(scf_e
);
1900 if (s
== NULL
|| i
== NULL
|| pg
== NULL
)
1903 if (is_svc_stn(class)) {
1904 tset
|= class_to_transition(class);
1906 if (!SCF_TRANS_VALID(tset
) || fmri
== NULL
) {
1907 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT
);
1911 if (decode_fmri(fmri
, h
, &s
, &i
) != SCF_SUCCESS
) {
1912 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED
)
1913 (void) scf_set_error(
1914 SCF_ERROR_INVALID_ARGUMENT
);
1915 if (check_scf_error(scf_error(), errs_1
)) {
1920 for (j
= 0; st_pgnames
[j
].st_pgname
!= NULL
; ++j
) {
1921 /* if this transition is not in the tset, continue */
1922 if (!(tset
& st_pgnames
[j
].st_state
))
1925 if (del_pg(s
, i
, st_pgnames
[j
].st_pgname
, pg
) !=
1927 scf_error() != SCF_ERROR_DELETED
&&
1928 scf_error() != SCF_ERROR_NOT_FOUND
) {
1929 if (check_scf_error(scf_error(),
1936 /* We only need to refresh the instance */
1937 if (_smf_refresh_instance_i(i
) != 0 &&
1938 check_scf_error(scf_error(), errs_1
))
1941 /* We have to refresh all instances in the service */
1942 if (_smf_refresh_all_instances(s
) != 0 &&
1943 check_scf_error(scf_error(), errs_1
))
1947 if ((pgname
= class_to_pgname(class)) == NULL
)
1950 if (scf_handle_decode_fmri(h
, SCF_NOTIFY_PARAMS_INST
, NULL
,
1951 NULL
, i
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
) != SCF_SUCCESS
)
1954 if (del_pg(NULL
, i
, pgname
, pg
) != SCF_SUCCESS
&&
1955 scf_error() != SCF_ERROR_DELETED
&&
1956 scf_error() != SCF_ERROR_NOT_FOUND
) {
1957 if (check_scf_error(scf_error(), errs_1
)) {
1962 if (_smf_refresh_instance_i(i
) != 0 &&
1963 check_scf_error(scf_error(), errs_1
))
1972 scf_instance_destroy(i
);
1973 scf_service_destroy(s
);
1974 scf_handle_destroy(h
);