/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include "libscf_impl.h"
#include <assert.h>
#include <strings.h>
/*
* Errors returned by smf_notify_{del|get|set}_params()
*/
0
};
/*
* Errors returned by smf_notify_{del|get|set}_params()
* Except SCF_ERROR_INVALID_ARGUMENT
*/
0
};
/*
* Helper function that abort() on unexpected errors.
* The expected error set is a zero-terminated array of scf_error_t
*/
static int
{
return (1);
assert(0);
abort();
/*NOTREACHED*/
}
/*
* Mapping of state transition to pgname.
*/
static struct st_pgname {
const char *st_pgname;
} st_pgnames[] = {
{ NULL, 0 }
};
/*
* Check if class matches or is a subclass of SCF_SVC_TRANSITION_CLASS
*
* returns 1, otherwise return 0
*/
static boolean_t
{
int n = strlen(SCF_SVC_TRANSITION_CLASS);
return (1);
return (0);
}
/*
* Return the len of the base class. For instance, "class.class1.class2.*"
* will return the length of "class.class1.class2"
* This function does not check if the class or base class is valid.
* A class such as "class.class1....****" is not valid but will return the
* length of "class.class1....***"
*/
static size_t
base_class_len(const char *c)
{
const char *p;
size_t n;
if ((n = strlen(c)) == 0)
return (0);
p = c + n;
/* get rid of any trailing asterisk */
if (*--p == '*')
n--;
/* make sure the class doesn't end in '.' */
while (p >= c && *--p == '.')
n--;
return (n);
}
/*
* Allocates and builds the pgname for an FMA dotted class.
* The pgname will be of the form "class.class1.class2,SCF_NOTIFY_PG_POSTFIX"
*
* NULL on error
*/
static char *
{
size_t n;
n = base_class_len(class);
if (n == 0) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
return (NULL);
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error;
}
SCF_NOTIFY_PG_POSTFIX) >= sz) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto error;
}
return (pgname);
return (pgname);
}
/*
* Get the pg from the running snapshot of the instance (composed or not)
*/
static int
{
scf_handle_t *h = scf_instance_handle(i);
int r = -1;
if (h == NULL) {
/*
* Use the error stored in scf_e
*/
(void) scf_set_error(scf_e);
goto out;
}
if (s == NULL) {
goto out;
goto out;
if (composed) {
goto out;
} else {
goto out;
}
} else {
if (scf_service_get_pg(s, n, pg) != 0)
goto out;
}
r = 0;
out:
return (r);
}
/*
* Add a pg if it does not exist, or get it if it exists.
* It operates on the instance if the service parameter is NULL.
*
* returns 0 on success or -1 on failure
*/
static int
{
int r;
if (s == NULL)
else
if (r == 0)
return (0);
else if (scf_error() != SCF_ERROR_EXISTS)
return (-1);
if (s == NULL)
r = scf_instance_get_pg(i, n, pg);
else
r = scf_service_get_pg(s, n, pg);
return (r);
}
/*
* Delete the property group form the instance or service.
* If service is NULL, use instance, otherwise use only the service.
*
* Return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_BACKEND_READONLY
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_HANDLE_MISMATCH
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_BOUND
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_NOT_SET
* SCF_ERROR_PERMISSION_DENIED
*/
static int
{
if (scf_error() == SCF_ERROR_NOT_FOUND)
return (SCF_SUCCESS);
else
return (SCF_FAILED);
if (scf_error() == SCF_ERROR_DELETED)
return (SCF_SUCCESS);
else
return (SCF_FAILED);
return (SCF_SUCCESS);
}
static scf_type_t
{
switch (nvpair_type(p)) {
case DATA_TYPE_BOOLEAN:
case DATA_TYPE_BOOLEAN_VALUE:
case DATA_TYPE_BOOLEAN_ARRAY:
return (SCF_TYPE_BOOLEAN);
case DATA_TYPE_BYTE:
case DATA_TYPE_UINT8:
case DATA_TYPE_UINT16:
case DATA_TYPE_UINT32:
case DATA_TYPE_UINT64:
case DATA_TYPE_BYTE_ARRAY:
case DATA_TYPE_UINT8_ARRAY:
case DATA_TYPE_UINT16_ARRAY:
case DATA_TYPE_UINT32_ARRAY:
case DATA_TYPE_UINT64_ARRAY:
return (SCF_TYPE_COUNT);
case DATA_TYPE_INT8:
case DATA_TYPE_INT16:
case DATA_TYPE_INT32:
case DATA_TYPE_INT64:
case DATA_TYPE_INT8_ARRAY:
case DATA_TYPE_INT16_ARRAY:
case DATA_TYPE_INT32_ARRAY:
case DATA_TYPE_INT64_ARRAY:
return (SCF_TYPE_INTEGER);
case DATA_TYPE_STRING:
case DATA_TYPE_STRING_ARRAY:
return (SCF_TYPE_ASTRING);
default:
return (SCF_TYPE_INVALID);
}
}
static int
{
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
static int
{
return (SCF_FAILED);
scf_value_set_boolean(val, v);
}
static int
{
return (SCF_FAILED);
scf_value_set_count(val, v);
}
static int
{
return (SCF_FAILED);
scf_value_set_integer(val, v);
}
static int
{
return (SCF_FAILED);
if (scf_value_set_astring(val, s) != 0) {
return (SCF_FAILED);
}
}
static int
{
uint_t n = 1;
int i;
return (SCF_FAILED);
switch (nvpair_type(p)) {
case DATA_TYPE_BOOLEAN:
case DATA_TYPE_BOOLEAN_VALUE:
{
boolean_t v;
(void) nvpair_value_boolean_value(p, &v);
}
case DATA_TYPE_BOOLEAN_ARRAY:
{
boolean_t *v;
(void) nvpair_value_boolean_array(p, &v, &n);
for (i = 0; i < n; ++i) {
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_BYTE:
{
uchar_t v;
(void) nvpair_value_byte(p, &v);
return (add_count_entry(h, te, v));
}
case DATA_TYPE_UINT8:
{
uint8_t v;
(void) nvpair_value_uint8(p, &v);
return (add_count_entry(h, te, v));
}
case DATA_TYPE_UINT16:
{
uint16_t v;
(void) nvpair_value_uint16(p, &v);
return (add_count_entry(h, te, v));
}
case DATA_TYPE_UINT32:
{
uint32_t v;
(void) nvpair_value_uint32(p, &v);
return (add_count_entry(h, te, v));
}
case DATA_TYPE_UINT64:
{
uint64_t v;
(void) nvpair_value_uint64(p, &v);
return (add_count_entry(h, te, v));
}
case DATA_TYPE_BYTE_ARRAY:
{
uchar_t *v;
(void) nvpair_value_byte_array(p, &v, &n);
for (i = 0; i < n; ++i) {
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_UINT8_ARRAY:
{
uint8_t *v;
(void) nvpair_value_uint8_array(p, &v, &n);
for (i = 0; i < n; ++i) {
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_UINT16_ARRAY:
{
uint16_t *v;
(void) nvpair_value_uint16_array(p, &v, &n);
for (i = 0; i < n; ++i) {
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_UINT32_ARRAY:
{
uint32_t *v;
(void) nvpair_value_uint32_array(p, &v, &n);
for (i = 0; i < n; ++i) {
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_UINT64_ARRAY:
{
uint64_t *v;
(void) nvpair_value_uint64_array(p, &v, &n);
for (i = 0; i < n; ++i) {
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_INT8:
{
int8_t v;
(void) nvpair_value_int8(p, &v);
return (add_integer_entry(h, te, v));
}
case DATA_TYPE_INT16:
{
int16_t v;
(void) nvpair_value_int16(p, &v);
return (add_integer_entry(h, te, v));
}
case DATA_TYPE_INT32:
{
int32_t v;
(void) nvpair_value_int32(p, &v);
return (add_integer_entry(h, te, v));
}
case DATA_TYPE_INT64:
{
int64_t v;
(void) nvpair_value_int64(p, &v);
return (add_integer_entry(h, te, v));
}
case DATA_TYPE_INT8_ARRAY:
{
int8_t *v;
(void) nvpair_value_int8_array(p, &v, &n);
for (i = 0; i < n; ++i) {
if (add_integer_entry(h, te, v[i]) !=
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_INT16_ARRAY:
{
int16_t *v;
(void) nvpair_value_int16_array(p, &v, &n);
for (i = 0; i < n; ++i) {
if (add_integer_entry(h, te, v[i]) !=
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_INT32_ARRAY:
{
int32_t *v;
(void) nvpair_value_int32_array(p, &v, &n);
for (i = 0; i < n; ++i) {
if (add_integer_entry(h, te, v[i]) !=
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_INT64_ARRAY:
{
int64_t *v;
(void) nvpair_value_int64_array(p, &v, &n);
for (i = 0; i < n; ++i) {
if (add_integer_entry(h, te, v[i]) !=
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
case DATA_TYPE_STRING:
{
char *str;
(void) nvpair_value_string(p, &str);
}
case DATA_TYPE_STRING_ARRAY:
{
char **v;
(void) nvpair_value_string_array(p, &v, &n);
for (i = 0; i < n; ++i) {
if (add_astring_entry(h, te, v[i]) !=
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
default:
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
return (SCF_FAILED);
}
/*NOTREACHED*/
}
/*
* Add new transaction entry to scf_transaction_t
*
* Can fail with
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
*/
static int
{
(scf_error() != SCF_ERROR_EXISTS ||
SCF_SUCCESS)) {
return (SCF_FAILED);
}
}
return (SCF_SUCCESS);
}
/*
* notify_set_params()
* returns 0 on success or -1 on failure
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_BACKEND_READONLY
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_PERMISSION_DENIED
*/
static int
{
int r = -1;
int err;
if (h == NULL) {
/*
* Use the error stored in scf_e
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
do {
/*
* make sure we have the most recent version of the pg
* start the transaction
*/
goto cleanup;
}
}
nvlist_t *m;
nvpair_t *p;
/* we ONLY take nvlists here */
/*
* if this is output from
* smf_notify_get_params() we want to skip
* the tset value of the nvlist
*/
continue;
(void) scf_set_error(
goto cleanup;
}
if (nvpair_value_nvlist(nvp, &m) != 0) {
(void) scf_set_error(
goto cleanup;
}
/*
* Traverse each mechanism list
*/
p = nvlist_next_nvpair(m, p)) {
scf_entry_create(h);
/* map the nvpair type to scf type */
if (scf_error() !=
goto cleanup;
} else {
assert(0);
abort();
}
}
if (type == SCF_TYPE_INVALID) {
(void) scf_set_error(
goto cleanup;
}
bufsz) {
(void) scf_set_error(
goto cleanup;
}
SCF_SUCCESS) {
goto cleanup;
}
if (check_scf_error(scf_error(),
errs_2)) {
goto cleanup;
}
}
}
}
} while (err == 0);
if (err == -1) {
goto cleanup;
}
}
r = 0;
return (r);
}
/*
* Decode fmri. Populates service OR instance depending on which one is an
* exact match to the fmri parameter.
*
* The function destroys and sets the unused entity (service or instance) to
* NULL.
*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_CONSTRAINT_VIOLATED
* SCF_ERROR_DELETED
* SCF_ERROR_HANDLE_MISMATCH
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_BOUND
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_NOT_SET
*/
static int
scf_instance_t **i)
{
SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) {
if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
scf_service_destroy(*s);
*s = NULL;
} else {
return (SCF_FAILED);
}
}
if (*s == NULL)
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
/*
* Return size in bytes for an SCF_TYPE_*. Not all libscf types are supported
*/
static int
{
switch (t) {
case SCF_TYPE_BOOLEAN:
return (sizeof (uint8_t));
case SCF_TYPE_COUNT:
return (sizeof (uint64_t));
case SCF_TYPE_INTEGER:
return (sizeof (int64_t));
case SCF_TYPE_ASTRING:
case SCF_TYPE_USTRING:
return (sizeof (void *));
default:
return (-1);
}
/*NOTREACHED*/
}
/*
* Return a pointer to the array of values according to its type
*/
static void **
{
switch (v->value_type) {
case SCF_TYPE_BOOLEAN:
case SCF_TYPE_COUNT:
case SCF_TYPE_INTEGER:
case SCF_TYPE_ASTRING:
case SCF_TYPE_USTRING:
default:
return (NULL);
}
/*NOTREACHED*/
}
/*
* Populate scf_values_t value array at position c.
*/
static int
{
switch (v->value_type) {
case SCF_TYPE_BOOLEAN:
case SCF_TYPE_COUNT:
case SCF_TYPE_INTEGER:
case SCF_TYPE_ASTRING:
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (-1);
}
return (0);
case SCF_TYPE_USTRING:
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (-1);
}
return (0);
default:
return (-1);
}
/*NOTREACHED*/
}
/*
* Populate scf_values_t structure with values from prop
*/
static int
{
void **p;
int r = SCF_FAILED;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
if (h == NULL) {
/*
* Use the error stored in scf_e
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
goto cleanup;
goto error;
p = get_v_pointer(v);
goto error;
}
void *tmp;
/* set initial size or double it */
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error;
}
*p = tmp;
}
goto error;
count++;
}
v->value_count = count;
if (err != 0)
goto error;
r = SCF_SUCCESS;
goto cleanup;
v->value_count = count;
return (r);
}
/*
* Add values from property p to existing nvlist_t nvl. The data type in the
* nvlist is inferred from the scf_type_t of the property.
*
* Returns SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_HANDLE_DESTROYED
* SCF_ERROR_HANDLE_MISMATCH
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_BOUND
* SCF_ERROR_NOT_SET
* SCF_ERROR_PERMISSION_DENIED
* SCF_ERROR_TYPE_MISMATCH
*/
static int
int array)
{
int r = SCF_FAILED;
int err = 0;
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
return (r);
}
if (scf_property_type(p, &type) != 0)
goto cleanup;
/*
* scf_values_t does not support subtypes of SCF_TYPE_USTRING,
* mapping them all to SCF_TYPE_USTRING
*/
if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) {
assert(0);
abort();
}
goto cleanup;
}
switch (vals.value_type) {
case SCF_TYPE_BOOLEAN:
{
boolean_t *v;
int i;
int n = vals.value_count;
if (v == NULL) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
for (i = 0; i < n; ++i)
if (n == 1 && !array)
else
v, n);
if (err != 0) {
free(v);
goto cleanup;
}
free(v);
}
break;
case SCF_TYPE_COUNT:
else
if (err != 0)
goto cleanup;
break;
case SCF_TYPE_INTEGER:
else
if (err != 0)
goto cleanup;
break;
case SCF_TYPE_ASTRING:
else
if (err != 0)
goto cleanup;
break;
default:
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
r = SCF_SUCCESS;
switch (err) {
case 0:
break;
case EINVAL:
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
break;
case ENOMEM:
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
break;
default:
/* we should *never* get here */
abort();
}
return (r);
}
/*
* Parse property name "mechanism,parameter" into separate mechanism
* and parameter. *mech must be freed by caller. *val points into
* *mech and must not be freed.
*
* Returns SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NOT_FOUND
*/
static int
{
char *p;
char *m;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (SCF_FAILED);
}
free(m);
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
return (SCF_FAILED);
}
*p = '\0';
*val = p + 1;
*mech = m;
return (SCF_SUCCESS);
}
/*
* Return the number of transitions in a transition set.
* If the transition set is invalid, it returns zero.
*/
static uint_t
{
int i;
int n = 0;
if (SCF_TRANS_VALID(t)) {
if (i & t)
++n;
if (SCF_TRANS_INITIAL_STATE(t) & i)
++n;
}
}
return (n);
}
/*
* Return the SCF_STATE_* macro value for the state in the FMA classes for
* SMF state transitions. They are of type:
* SCF_SVC_TRANSITION_CLASS.<state>
* ireport.os.smf.state-transition.<state>
*/
static int32_t
class_to_transition(const char *c)
{
const char *p;
int r = 0;
size_t n;
if (!is_svc_stn(c)) {
return (0);
}
/*
* if we get here, c is SCF_SVC_TRANSITION_CLASS or longer
*/
p = c + strlen(SCF_SVC_TRANSITION_CLASS);
if (*p == '.')
++p;
else
return (0);
if ((n = base_class_len(p)) == 0)
return (0);
if ((r = state_from_string(p, n)) == -1)
r = 0;
return (r);
}
/*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_BACKEND_READONLY
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_PERMISSION_DENIED
*/
int
{
scf_service_t *s = scf_service_create(h);
scf_instance_t *i = scf_instance_create(h);
int r = SCF_FAILED;
int j;
if (h == NULL) {
/*
* use saved error if _scf_handle_create_and_bind() fails
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
/* check version */
ver != SCF_NOTIFY_PARAMS_VERSION) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
/* special case SMF state transition notification */
if (is_stn &&
!SCF_TRANS_VALID(tset))) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
if (is_stn) {
if (!SCF_TRANS_VALID(tset)) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
/* if this transition is not in the tset, continue */
continue;
SCF_NOTIFY_PARAMS_PG_TYPE, 0, pg) != 0 &&
goto cleanup;
goto cleanup;
}
if (s == NULL) {
/* We only need to refresh the instance */
if (_smf_refresh_instance_i(i) != 0 &&
goto cleanup;
} else {
/* We have to refresh all instances in the service */
if (_smf_refresh_all_instances(s) != 0 &&
goto cleanup;
}
} else {
goto cleanup;
0) {
goto cleanup;
}
}
goto cleanup;
}
if (_smf_refresh_instance_i(i) != 0 &&
goto cleanup;
}
r = SCF_SUCCESS;
return (r);
}
/*
* returns SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_HANDLE_DESTROYED
* SCF_ERROR_HANDLE_MISMATCH
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_BOUND
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_NOT_SET
* SCF_ERROR_PERMISSION_DENIED
*/
int
{
scf_property_t *p = scf_property_create(h);
int r = SCF_FAILED;
int err;
if (h == NULL) {
/*
* Use the error stored in scf_e
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
goto cleanup;
}
}
int nvl_new = 0;
char *mech;
char *val;
goto cleanup;
}
}
if (scf_error() == SCF_ERROR_NOT_FOUND)
continue;
goto cleanup;
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
nvl_new = 1;
}
goto cleanup;
}
}
if (nvl_new) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
}
}
if (err == 0) {
r = SCF_SUCCESS;
goto cleanup;
}
return (r);
}
/*
* Look up pg containing an SMF state transition parameters. If it cannot find
* the pg in the composed view of the instance, it will look in the global
* instance for the system wide parameters.
* Instance, service and global instance have to be passed by caller.
*
* returns SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_HANDLE_DESTROYED
* SCF_ERROR_HANDLE_MISMATCH
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_BOUND
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_NOT_SET
*/
static int
{
scf_error() == SCF_ERROR_NOT_FOUND &&
return (SCF_SUCCESS);
return (SCF_FAILED);
}
/*
* Populates nvlist_t params with the source fmri for the pg
*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_DELETED
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_NO_MEMORY
*/
static int
{
char *p;
int r = SCF_FAILED;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto out;
}
goto out;
}
}
/* get rid of the properties part of the pg source */
*(p - 1) = '\0';
0) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto out;
}
r = SCF_SUCCESS;
out:
return (r);
}
/*
* Specialized function to get SMF state transition notification parameters
*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_PERMISSION_DENIED
*/
int
{
scf_service_t *s = scf_service_create(h);
scf_instance_t *i = scf_instance_create(h);
scf_instance_t *g = scf_instance_create(h);
int r = SCF_FAILED;
int j;
const char *pgname;
if (h == NULL) {
/*
* use saved error if _scf_handle_create_and_bind() fails
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
NULL, SCF_DECODE_FMRI_EXACT) != 0) {
if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
for (c = 0; c < nvl_num; ++c)
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
/* if this transition is not in the tset, continue */
continue;
st_pgnames[j].st_state) != 0) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
not_found = 0;
goto cleanup;
goto cleanup;
} else if (scf_error() == SCF_ERROR_NOT_FOUND ||
scf_error() == SCF_ERROR_DELETED) {
/* keep driving */
/*EMPTY*/
goto cleanup;
}
++c;
}
if (not_found) {
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
goto cleanup;
}
SCF_NOTIFY_PARAMS_VERSION) != 0) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
r = SCF_SUCCESS;
for (c = 0; c < nvl_num; ++c)
nvlist_free(params[c]);
return (r);
}
/*
* Specialized function to get fma notification parameters
*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_PERMISSION_DENIED
*/
int
{
scf_instance_t *i = scf_instance_create(h);
int r = SCF_FAILED;
if (h == NULL) {
/*
* use saved error if _scf_handle_create_and_bind() fails
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
goto cleanup;
}
}
goto cleanup;
if (scf_error() == SCF_ERROR_NOT_FOUND) {
if (p != NULL) {
*p = ',';
/*
* since the resulting string is shorter,
* there is no risk of buffer overflow
*/
continue;
}
}
goto cleanup;
}
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
goto cleanup;
goto cleanup;
SCF_NOTIFY_PARAMS_VERSION) != 0) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto cleanup;
}
r = SCF_SUCCESS;
if (params)
return (r);
}
/*
* Retrieve the notification parameters for the Event described in the
* input nvlist_t nvl.
* The function will allocate an nvlist_t to store the notification
* parameters. The notification parameters in the output nvlist will have
* the following format:
*
* version (uint32_t)
* SCF_NOTIFY_PARAMS (array of embedded nvlists)
* (start of notify-params[0])
* tset (int32_t)
* <mechanism-name> (embedded nvlist)
* <parameter-name> <parameter-type>
* ...
* (end <mechanism-name>)
* ...
* (end of notify-params[0])
* ...
*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_PERMISSION_DENIED
*/
int
{
char *class;
char *fmri;
int r = SCF_FAILED;
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
return (r);
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (r);
}
if (is_svc_stn(class)) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
if (!SCF_TRANS_VALID(tset)) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
} else {
}
if (r == SCF_FAILED) {
}
return (r);
}
/*
* return SCF_SUCCESS or SCF_FAILED on
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_BACKEND_READONLY
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_DELETED
* SCF_ERROR_INTERNAL
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NOT_FOUND
* SCF_ERROR_PERMISSION_DENIED
*/
int
{
scf_service_t *s = scf_service_create(h);
scf_instance_t *i = scf_instance_create(h);
int r = SCF_FAILED;
int j;
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
if (h == NULL) {
/*
* use saved error if _scf_handle_create_and_bind() fails
*/
(void) scf_set_error(scf_e);
goto cleanup;
}
goto cleanup;
if (is_svc_stn(class)) {
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto cleanup;
}
if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
(void) scf_set_error(
goto cleanup;
}
}
/* if this transition is not in the tset, continue */
continue;
SCF_SUCCESS &&
scf_error() != SCF_ERROR_DELETED &&
scf_error() != SCF_ERROR_NOT_FOUND) {
if (check_scf_error(scf_error(),
errs_1)) {
goto cleanup;
}
}
}
if (s == NULL) {
/* We only need to refresh the instance */
if (_smf_refresh_instance_i(i) != 0 &&
goto cleanup;
} else {
/* We have to refresh all instances in the service */
if (_smf_refresh_all_instances(s) != 0 &&
goto cleanup;
}
} else {
goto cleanup;
goto cleanup;
scf_error() != SCF_ERROR_DELETED &&
scf_error() != SCF_ERROR_NOT_FOUND) {
goto cleanup;
}
}
if (_smf_refresh_instance_i(i) != 0 &&
goto cleanup;
}
r = SCF_SUCCESS;
return (r);
}