midlevel.c revision afffa6e9b45cbe9b33943e26568d8ac69b899252
/*
* 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
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include "libscf_impl.h"
#include <assert.h>
#include <libuutil.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <libgen.h>
#include <assert.h>
#include "midlevel_impl.h"
#include "lowlevel_impl.h"
#ifndef NDEBUG
uu_warn("%s:%d: %s failed with unexpected error %d. Aborting.\n", \
abort(); \
}
#else
#endif
/* Path to speedy files area must end with a slash */
#define SMF_SPEEDY_FILES_PATH "/etc/svc/volatile/"
void
{
return;
}
/*
* Given a base service FMRI and the names of a property group and property,
* assemble_fmri() merges them into a property FMRI. Note that if the base
* FMRI is NULL, assemble_fmri() gets the base FMRI from scf_myname().
*/
static char *
const char *prop)
{
char *fmri_buf;
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
return (NULL);
}
else
return (NULL);
} else {
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
}
return (NULL);
}
} else {
}
else
return (fmri_buf);
}
/*
* Given a property, this function allocates and fills an scf_simple_prop_t
* with the data it contains.
*/
static scf_simple_prop_t *
scf_handle_t *h)
{
int iterret, i;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
}
else
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
}
goto error3;
goto error3;
goto error3;
}
goto error1;
numvals++) {
goto error1;
}
case SCF_TYPE_BOOLEAN:
if (scf_value_get_boolean(val,
goto error1;
break;
case SCF_TYPE_COUNT:
if (scf_value_get_count(val,
goto error1;
break;
case SCF_TYPE_INTEGER:
if (scf_value_get_integer(val,
goto error1;
break;
case SCF_TYPE_TIME:
if (scf_value_get_time(val,
goto error1;
break;
case SCF_TYPE_ASTRING:
-1)
goto error1;
NULL) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
if (scf_value_get_astring(val,
goto error1;
}
break;
case SCF_TYPE_USTRING:
case SCF_TYPE_HOST:
case SCF_TYPE_HOSTNAME:
case SCF_TYPE_NET_ADDR:
case SCF_TYPE_NET_ADDR_V4:
case SCF_TYPE_NET_ADDR_V6:
case SCF_TYPE_URI:
case SCF_TYPE_FMRI:
-1)
goto error1;
NULL) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
if (scf_value_get_ustring(val,
goto error1;
}
break;
case SCF_TYPE_OPAQUE:
-1)
goto error1;
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
if (scf_value_get_opaque(val,
valsize) == -1) {
goto error1;
}
break;
default:
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
}
if (iterret == -1) {
if (err != SCF_ERROR_CONNECTION_BROKEN &&
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
(void) scf_value_destroy(val);
return (ret);
/*
* Exit point for a successful call. Below this line are exit points
* for failures at various stages during the function.
*/
goto error2;
case SCF_TYPE_ASTRING:
case SCF_TYPE_USTRING:
case SCF_TYPE_HOST:
case SCF_TYPE_HOSTNAME:
case SCF_TYPE_NET_ADDR:
case SCF_TYPE_NET_ADDR_V4:
case SCF_TYPE_NET_ADDR_V6:
case SCF_TYPE_URI:
case SCF_TYPE_FMRI: {
for (i = 0; i < numvals; i++) {
}
break;
}
case SCF_TYPE_OPAQUE: {
for (i = 0; i < numvals; i++) {
}
break;
}
default:
break;
}
(void) scf_value_destroy(val);
return (NULL);
}
/*
* insert_app_props iterates over a property iterator, getting all the
* properties from a property group, and adding or overwriting them into
* a simple_app_props_t. This is used by scf_simple_app_props_get to provide
* insert_app_props iterates over a single property group.
*/
static int
scf_handle_t *h)
{
int propiter_ret;
if (scf_error() == SCF_ERROR_NOT_SET)
(void) scf_set_error(SCF_ERROR_INTERNAL);
return (-1);
}
found = 0;
found = 1;
return (-1);
else
} else {
}
}
if (!found) {
NULL)
return (-1);
else
}
}
if (propiter_ret == -1) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
return (-1);
}
return (0);
}
/*
* Sets up e in tx to set pname's values. Returns 0 on success or -1 on
* failure, with scf_error() set to
* SCF_ERROR_HANDLE_MISMATCH - tx & e are derived from different handles
* SCF_ERROR_INVALID_ARGUMENT - pname or ty are invalid
* SCF_ERROR_NOT_BOUND - handle is not bound
* SCF_ERROR_CONNECTION_BROKEN - connection was broken
* SCF_ERROR_NOT_SET - tx has not been started
* SCF_ERROR_DELETED - the pg tx was started on was deleted
*/
static int
{
for (;;) {
return (0);
switch (scf_error()) {
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
case SCF_ERROR_DELETED:
default:
return (-1);
case SCF_ERROR_NOT_FOUND:
break;
}
return (0);
switch (scf_error()) {
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
case SCF_ERROR_DELETED:
default:
return (-1);
case SCF_ERROR_EXISTS:
break;
}
}
}
static int
{
scf_value_t *v = NULL;
scf_handle_t *h = NULL;
int ret = -1;
return (-1);
(v = scf_value_create(h)) == NULL)
goto out;
scf_property_get_value(eprop, v) ||
scf_value_get_boolean(v, &enabled))
goto out;
out:
return (ret);
}
/*
* instance and the desired state for the enabled bit in the instance's
* named property group. If the group doesn't exist, it's created with the
* given flags. Called by smf_{dis,en}able_instance().
*/
static int
{
scf_value_t *v = NULL;
scf_handle_t *h = NULL;
int ret = -1;
int committed;
uint8_t b;
return (-1);
(v = scf_value_create(h)) == NULL ||
goto out;
if (scf_error() != SCF_ERROR_NOT_FOUND)
goto out;
if (scf_error() != SCF_ERROR_EXISTS)
goto out;
goto general_pg_get;
}
}
get:
if (scf_error() != SCF_ERROR_NOT_FOUND)
goto out;
if (scf_error() != SCF_ERROR_EXISTS)
goto out;
goto get;
}
}
}
if (scf_error() != SCF_ERROR_NOT_FOUND)
goto out;
else
goto set;
}
/*
* If it's already set the way we want, forgo the transaction.
*/
switch (scf_error()) {
case SCF_ERROR_NOT_FOUND:
/* Misconfigured, so set anyway. */
goto set;
default:
goto out;
}
}
if (scf_value_get_boolean(v, &b) == -1) {
if (scf_error() != SCF_ERROR_TYPE_MISMATCH)
goto out;
goto set;
}
if (b == desired) {
ret = 0;
goto out;
}
set:
do {
goto out;
SCF_TYPE_BOOLEAN) != 0) {
switch (scf_error()) {
case SCF_ERROR_DELETED:
default:
goto out;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
bad_error("transaction_property_set",
scf_error());
}
}
goto out;
if (committed == -1)
goto out;
if (committed == 0) { /* out-of-sync */
goto out;
}
} while (committed == 0);
ret = 0;
out:
return (ret);
}
static int
{
scf_handle_t *h = NULL;
int ret = -1;
int committed;
return (-1);
goto out;
goto error;
do {
SCF_PROPERTY_ENABLED) == -1 ||
goto error;
goto error;
} while (committed == 0);
ret = 0;
goto out;
switch (scf_error()) {
case SCF_ERROR_DELETED:
case SCF_ERROR_NOT_FOUND:
/* success */
ret = 0;
}
out:
return (ret);
}
/*
* Returns 0 on success or -1 on failure. On failure leaves scf_error() set to
* SCF_ERROR_HANDLE_DESTROYED - inst's handle has been destroyed
* SCF_ERROR_NOT_BOUND - inst's handle is not bound
* SCF_ERROR_CONNECTION_BROKEN - the repository connection was broken
* SCF_ERROR_NOT_SET - inst is not set
* SCF_ERROR_DELETED - inst was deleted
* SCF_ERROR_PERMISSION_DENIED
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_BACKEND_READONLY
*/
static int
{
scf_handle_t *h;
scf_value_t *v = NULL;
int64_t t;
(v = scf_value_create(h)) == NULL ||
goto out;
get:
switch (scf_error()) {
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
case SCF_ERROR_DELETED:
default:
goto out;
case SCF_ERROR_NOT_FOUND:
break;
}
/* Try creating the restarter_actions property group. */
add:
switch (scf_error()) {
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
case SCF_ERROR_DELETED:
case SCF_ERROR_BACKEND_ACCESS:
default:
goto out;
case SCF_ERROR_EXISTS:
goto get;
}
}
}
for (;;) {
switch (scf_error()) {
default:
goto out;
case SCF_ERROR_DELETED:
goto add;
case SCF_ERROR_NOT_FOUND:
break;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
}
} else if (scf_property_get_value(prop, v) != 0) {
switch (scf_error()) {
default:
goto out;
case SCF_ERROR_DELETED:
goto add;
case SCF_ERROR_NOT_FOUND:
break;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
bad_error("scf_property_get_value",
scf_error());
}
} else if (scf_value_get_integer(v, &t) != 0) {
} else if (t > timestamp) {
break;
}
switch (scf_error()) {
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_BACKEND_ACCESS:
default:
goto out;
case SCF_ERROR_DELETED:
goto add;
case SCF_ERROR_NOT_SET:
case SCF_ERROR_IN_USE:
}
}
SCF_TYPE_INTEGER) != 0) {
switch (scf_error()) {
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_DELETED:
default:
goto out;
case SCF_ERROR_NOT_SET:
bad_error("transaction_property_set",
scf_error());
}
}
if (trans == 1)
break;
if (trans != 0) {
switch (scf_error()) {
case SCF_ERROR_BACKEND_ACCESS:
default:
goto out;
case SCF_ERROR_DELETED:
goto add;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
bad_error("scf_transaction_commit",
scf_error());
}
}
switch (scf_error()) {
default:
goto out;
case SCF_ERROR_DELETED:
goto add;
case SCF_ERROR_NOT_SET:
case SCF_ERROR_NOT_BOUND:
}
}
}
ret = 0;
out:
return (ret);
}
static int
{
scf_handle_t *h;
int ret = -1;
if (h == NULL)
return (-1);
inst = scf_instance_create(h);
NULL, SCF_DECODE_FMRI_EXACT) == 0) {
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
} else {
switch (scf_error()) {
(void) scf_set_error(
break;
case SCF_ERROR_DELETED:
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
break;
}
}
}
return (ret);
}
/*
* get_inst_state() gets the state string from an instance, and returns
* the SCF_STATE_* constant that coincides with the instance's current state.
*/
static int
{
char state[MAX_SCF_STATE_STRING_SZ];
int ret = -1;
goto out;
/* Pull the state property from the instance */
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto out;
}
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto out;
}
}
out:
(void) scf_value_destroy(val);
return (ret);
}
/*
* Sets an instance to be enabled or disabled after reboot, using the
* temporary (overriding) general_ovr property group to reflect the
* present state, if it is different.
*/
static int
{
int enabled;
int persistent;
int ret = -1;
if (scf_error() != SCF_ERROR_NOT_FOUND)
goto out;
}
if (persistent != desired) {
/*
* Temporarily store the present enabled state.
*/
goto out;
}
}
if (persistent != desired)
goto out;
else
ret = 0;
out:
return (ret);
}
static int
{
int ret = -1;
scf_handle_t *h;
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
return (ret);
}
return (ret);
return (ret);
}
SCF_DECODE_FMRI_EXACT) == -1) {
if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto out;
}
if (flags & SMF_AT_NEXT_BOOT) {
} else {
goto out;
/*
* Make the persistent value effective by deleting the
* temporary one.
*/
if (flags & SMF_TEMPORARY)
ret = 0;
else
}
out:
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
return (ret);
}
/*
* Create and return a pg from the instance associated with the given handle.
* This function is only called in scf_transaction_setup and
* scf_transaction_restart where the h->rh_instance pointer is properly filled
* in by scf_general_setup_pg().
*/
static scf_propertygroup_t *
{
char *pg_name;
return (NULL);
}
if (scf_error() == SCF_ERROR_NOT_SET) {
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
}
return (NULL);
}
if (scf_error() == SCF_ERROR_NOT_SET) {
(void) scf_set_error(SCF_ERROR_INTERNAL);
}
return (NULL);
}
/* Get pg from instance */
return (NULL);
}
return (ret_pg);
}
int
{
}
int
{
}
int
{
}
int
{
scf_handle_t *h = scf_service_handle(s);
scf_instance_t *i = scf_instance_create(h);
int err, r = -1;
goto error;
if (scf_iter_service_instances(it, s) != 0)
goto error;
if (_smf_refresh_instance_i(i) != 0)
goto error;
if (err == -1)
goto error;
r = 0;
return (r);
}
int
smf_refresh_instance(const char *instance)
{
}
int
smf_restart_instance(const char *instance)
{
}
int
{
if (flags & SMF_TEMPORARY)
return (set_inst_action(instance,
(flags & SMF_IMMEDIATE) ?
else
return (set_inst_action(instance,
(flags & SMF_IMMEDIATE) ?
}
int
{
const char *state_str;
if (flags & SMF_TEMPORARY)
return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT));
SCF_PROPERTY_STATE)) == NULL)
return (SCF_FAILED);
return (SCF_FAILED);
}
return (scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED));
}
}
int
smf_restore_instance(const char *instance)
{
const char *state_str;
int ret;
SCF_PROPERTY_STATE)) == NULL)
return (SCF_FAILED);
return (SCF_FAILED);
}
} else {
}
return (ret);
}
char *
smf_get_state(const char *instance)
{
const char *state_str;
char *ret;
SCF_PROPERTY_STATE)) == NULL)
return (NULL);
return (NULL);
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (ret);
}
/*
* scf_general_pg_setup(fmri, pg_name)
* Create a scf_simple_handle_t and fill in the instance, snapshot, and
* property group fields associated with the given fmri and property group
* name.
* Returns:
* Handle on success
* Null on error with scf_error set to:
* SCF_ERROR_HANDLE_MISMATCH,
* SCF_ERROR_INVALID_ARGUMENT,
* SCF_ERROR_CONSTRAINT_VIOLATED,
* SCF_ERROR_NOT_FOUND,
* SCF_ERROR_NOT_SET,
* SCF_ERROR_DELETED,
* SCF_ERROR_NOT_BOUND,
* SCF_ERROR_CONNECTION_BROKEN,
* SCF_ERROR_INTERNAL,
* SCF_ERROR_NO_RESOURCES,
* SCF_ERROR_BACKEND_ACCESS
*/
{
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
} else {
}
goto out;
}
goto out;
}
!= 0) {
goto out;
}
ret->running_pg) != 0) {
goto out;
}
return (ret);
out:
return (NULL);
}
/*
* scf_transaction_setup(h)
* creates and starts the transaction
* Returns:
* transaction on success
* NULL on failure with scf_error set to:
* SCF_ERROR_NO_MEMORY,
* SCF_ERROR_INVALID_ARGUMENT,
* SCF_ERROR_HANDLE_DESTROYED,
* SCF_ERROR_INTERNAL,
* SCF_ERROR_NO_RESOURCES,
* SCF_ERROR_NOT_BOUND,
* SCF_ERROR_CONNECTION_BROKEN,
* SCF_ERROR_NOT_SET,
* SCF_ERROR_DELETED,
* SCF_ERROR_CONSTRAINT_VIOLATED,
* SCF_ERROR_HANDLE_MISMATCH,
* SCF_ERROR_BACKEND_ACCESS,
* SCF_ERROR_IN_USE
*/
{
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (tx);
}
int
{
return (SCF_FAILED);
}
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
/*
* scf_read_count_property(scf_simple_handle_t *simple_h, char *prop_name,
* uint64_t *ret_count)
*
* For the given property name, return the count value.
* RETURNS:
* SCF_SUCCESS
* SCF_FAILED on failure with scf_error() set to:
* SCF_ERROR_HANDLE_DESTROYED
* SCF_ERROR_INTERNAL
* SCF_ERROR_NO_RESOURCES
* SCF_ERROR_NO_MEMORY
* SCF_ERROR_HANDLE_MISMATCH
* SCF_ERROR_INVALID_ARGUMENT
* SCF_ERROR_NOT_BOUND
* SCF_ERROR_CONNECTION_BROKEN
* SCF_ERROR_NOT_SET
* SCF_ERROR_DELETED
* SCF_ERROR_BACKEND_ACCESS
* SCF_ERROR_CONSTRAINT_VIOLATED
* SCF_ERROR_TYPE_MISMATCH
*/
int
char *prop_name,
{
int ret = SCF_FAILED;
goto out;
}
/*
* Get the property struct that goes with this property group and
* property name.
*/
goto out;
}
/* Get the value structure */
goto out;
}
/*
* Now get the count value.
*/
goto out;
}
ret = SCF_SUCCESS;
out:
return (ret);
}
/*
* scf_trans_add_count_property(trans, propname, count, create_flag)
*
* Set a count property transaction entry into the pending SMF transaction.
* The transaction is created and committed outside of this function.
* Returns:
* SCF_SUCCESS
* SCF_FAILED on failure with scf_error() set to:
* SCF_ERROR_HANDLE_DESTROYED,
* SCF_ERROR_INVALID_ARGUMENT,
* SCF_ERROR_NO_MEMORY,
* SCF_ERROR_HANDLE_MISMATCH,
* SCF_ERROR_NOT_SET,
* SCF_ERROR_IN_USE,
* SCF_ERROR_NOT_FOUND,
* SCF_ERROR_EXISTS,
* SCF_ERROR_TYPE_MISMATCH,
* SCF_ERROR_NOT_BOUND,
* SCF_ERROR_CONNECTION_BROKEN,
* SCF_ERROR_INTERNAL,
* SCF_ERROR_DELETED,
* SCF_ERROR_NO_RESOURCES,
* SCF_ERROR_BACKEND_ACCESS
*/
int
char *propname,
{
return (SCF_FAILED);
}
/*
* Property must be set in transaction and won't take
* effect until the transaction is committed.
*
* Attempt to change the current value. However, create new property
* if it doesn't exist and the create flag is set.
*/
SCF_TYPE_COUNT) == 0) {
return (SCF_SUCCESS);
}
} else {
if ((create_flag == B_TRUE) &&
(scf_error() == SCF_ERROR_NOT_FOUND)) {
SCF_TYPE_COUNT) == 0) {
return (SCF_SUCCESS);
}
}
}
}
/*
* cleanup if there were any errors that didn't leave these
* values where they would be cleaned up later.
*/
return (SCF_FAILED);
}
int
{
scf_handle_t *h = NULL;
int ret = SCF_FAILED;
int svc_iter_ret, inst_iter_ret;
int inst_state;
return (ret);
goto out;
/*
* Get the local scope, and set up nested iteration through every
* local service, and every instance of every service.
*/
goto out;
goto out;
while ((inst_iter_ret =
/*
* If get_inst_state fails from an internal error,
* IE, being unable to get the property group or
* property containing the state of the instance,
* we continue instead of failing, as this might just
* be an improperly configured instance.
*/
if (scf_error() == SCF_ERROR_INTERNAL) {
continue;
} else {
goto out;
}
}
SCF_SUCCESS) {
(void) scf_set_error(
goto out;
}
}
}
if (inst_iter_ret == -1)
goto out;
}
if (svc_iter_ret != -1)
ret = SCF_SUCCESS;
out:
return (ret);
}
const char *propname)
{
scf_handle_t *h = NULL;
/* If the user passed in a handle, use it. */
h = hin;
}
return (NULL);
if (local_h)
return (NULL);
}
goto error1;
SCF_DECODE_FMRI_REQUIRE_INSTANCE) == -1) {
switch (scf_error()) {
/*
* If the property isn't found in the instance, we grab the
* underlying service, create an FMRI out of it, and then
* query the datastore again at the service level for the
* property.
*/
case SCF_ERROR_NOT_FOUND:
goto error1;
goto error1;
goto error1;
goto error1;
}
break;
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
default:
goto error1;
}
}
/*
* At this point, we've successfully pulled the property from the
* datastore, and simply need to copy its innards into an
* scf_simple_prop_t.
*/
goto error1;
if (local_h)
return (ret);
/*
* Exit point for a successful call. Below this line are exit points
* for failures at various stages during the function.
*/
if (local_h)
return (NULL);
}
void
{
int i;
return;
case SCF_TYPE_OPAQUE: {
for (i = 0; i < prop->pr_numvalues; i++) {
}
break;
}
case SCF_TYPE_ASTRING:
case SCF_TYPE_USTRING:
case SCF_TYPE_HOST:
case SCF_TYPE_HOSTNAME:
case SCF_TYPE_NET_ADDR:
case SCF_TYPE_NET_ADDR_V4:
case SCF_TYPE_NET_ADDR_V6:
case SCF_TYPE_URI:
case SCF_TYPE_FMRI: {
for (i = 0; i < prop->pr_numvalues; i++) {
}
break;
}
default:
break;
}
}
{
scf_handle_t *h = NULL;
int pgiter_ret, propiter_ret;
/* If the user passed in a handle, use it. */
h = hin;
}
return (NULL);
if (local_h)
return (NULL);
}
if (local_h)
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
}
if (local_h)
return (NULL);
}
} else {
if (local_h)
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
return (NULL);
}
}
goto error2;
}
SCF_DECODE_FMRI_REQUIRE_INSTANCE) == -1) {
if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
(void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
goto error2;
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error2;
}
0) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
} else {
/* This is the first iteration */
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
if (scf_error() == SCF_ERROR_NOT_SET)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
== 1) {
0) {
if (scf_error() == SCF_ERROR_NOT_SET)
(void) scf_set_error(
goto error1;
}
goto error1;
} else {
/* This is the first iteration */
goto error1;
}
}
if (propiter_ret == -1) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
}
if (pgiter_ret == -1) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
/*
* At this point, we've filled the scf_simple_app_props_t with all the
* properties at the service level. Now we iterate over all the
* properties at the instance level, overwriting any duplicate
*/
!= 0) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
found = 0;
/*
* Find either the end of the list, so we can append the
* property group, or an existing property group that matches
*/
if (scf_error() == SCF_ERROR_NOT_SET)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
found = 1;
break;
}
break;
}
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
if (found) {
/*
* insert_app_props inserts or overwrites the
* properties in thispg.
*/
goto error1;
} else {
/*
* If the property group wasn't found, we're adding
* a newly allocated property group to the end of the
* list.
*/
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
(void) scf_set_error(SCF_ERROR_NO_MEMORY);
goto error1;
}
} else {
}
while ((propiter_ret =
namelen) < 0) {
if (scf_error() == SCF_ERROR_NOT_SET)
(void) scf_set_error(
goto error1;
}
NULL)
goto error1;
} else {
/* This is the first iteration */
NULL)
goto error1;
}
}
if (propiter_ret == -1) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(
goto error1;
}
}
}
if (pgiter_ret == -1) {
if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
(void) scf_set_error(SCF_ERROR_INTERNAL);
goto error1;
}
goto error1;
if (local_h)
return (ret);
/*
* Exit point for a successful call. Below this line are exit points
* for failures at various stages during the function.
*/
if (local_h)
return (NULL);
}
void
{
return;
}
}
}
const scf_simple_prop_t *
{
struct scf_simple_pg *this;
(void) scf_set_error(SCF_ERROR_NOT_SET);
return (NULL);
}
/*
* We're looking for the first property in this block if last is
* NULL
*/
/* An empty pglist is legal, it just means no properties */
(void) scf_set_error(SCF_ERROR_NONE);
return (NULL);
}
/*
* Walk until we find a pg with a property in it, or we run
* out of property groups.
*/
(void) scf_set_error(SCF_ERROR_NONE);
return (NULL);
}
return (this->pg_proplist);
}
/*
* If last isn't NULL, then return the next prop in the property group,
* or walk the property groups until we find another property, or
* run out of property groups.
*/
(void) scf_set_error(SCF_ERROR_NONE);
return (NULL);
}
(void) scf_set_error(SCF_ERROR_NONE);
return (NULL);
}
return (this->pg_proplist);
}
const scf_simple_prop_t *
{
struct scf_simple_pg *pg;
(void) scf_set_error(SCF_ERROR_NOT_SET);
return (NULL);
}
/*
* If pgname is NULL, we're searching the default application
* property group, otherwise we look for the specified group.
*/
} else {
}
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
return (NULL);
}
(void) scf_set_error(SCF_ERROR_NOT_FOUND);
return (NULL);
}
return (prop);
}
void
{
return;
}
{
return (scf_set_error(SCF_ERROR_NOT_SET));
return (prop->pr_numvalues);
}
{
return (scf_set_error(SCF_ERROR_NOT_SET));
}
char *
{
(void) scf_set_error(SCF_ERROR_NOT_SET);
return (NULL);
}
return (prop->pr_propname);
}
char *
{
(void) scf_set_error(SCF_ERROR_NOT_SET);
return (NULL);
}
}
static union scf_simple_prop_val *
{
(void) scf_set_error(SCF_ERROR_NOT_SET);
return (NULL);
}
case SCF_TYPE_USTRING:
case SCF_TYPE_HOST:
case SCF_TYPE_HOSTNAME:
case SCF_TYPE_NET_ADDR:
case SCF_TYPE_NET_ADDR_V4:
case SCF_TYPE_NET_ADDR_V6:
case SCF_TYPE_URI:
case SCF_TYPE_FMRI: {
if (type != SCF_TYPE_USTRING) {
(void) scf_set_error(SCF_ERROR_TYPE_MISMATCH);
return (NULL);
}
break;
}
default: {
(void) scf_set_error(SCF_ERROR_TYPE_MISMATCH);
return (NULL);
}
break;
}
}
(void) scf_set_error(SCF_ERROR_NONE);
return (NULL);
}
}
uint8_t *
{
union scf_simple_prop_val *ret;
return (NULL);
}
uint64_t *
{
union scf_simple_prop_val *ret;
return (NULL);
}
int64_t *
{
union scf_simple_prop_val *ret;
return (NULL);
}
int64_t *
{
union scf_simple_prop_val *ret;
return (NULL);
}
char *
{
union scf_simple_prop_val *ret;
return (NULL);
}
char *
{
union scf_simple_prop_val *ret;
return (NULL);
}
void *
{
union scf_simple_prop_val *ret;
*length = 0;
return (NULL);
}
}
/*
* Generate a filename based on the fmri and the given name and return
* it in the buffer of MAXPATHLEN provided by the caller.
* If temp_filename is non-zero, also generate a temporary, unique filename
* and return it in the temp buffer of MAXPATHLEN provided by the caller.
* The path to the generated pathname is also created.
* Given fmri should begin with a scheme such as "svc:".
* Returns
* 0 on success
* -1 if filename would exceed MAXPATHLEN or
* -2 if unable to create directory to filename path
*/
int
char *temp_filename)
{
int len;
if (len > MAXPATHLEN)
return (-1);
/* Construct directory name first - speedy path ends in slash */
/* errno is set */
return (-2);
}
if (temp_filename) {
}
return (0);
}
{
do {
return (base);
}
/*
* Convenience routine which frees all strings and opaque data
* allocated by scf_read_propvec.
*
* Like free(3C), this function preserves the value of errno.
*/
void
{
int saved_errno = errno;
}
}
errno = saved_errno;
}
static int
{
int count = 0;
count++;
return (count);
}
/*
* If 'running' is true, reads from the running snapshot instead of the
* editing snapshot.
*
* For string types, a buffer is allocated using malloc(3C) to hold the
* zero-terminated string, a pointer to which is stored in the
* caller-provided char **. It is the caller's responsbility to free
* this string. To simplify error handling, unread strings are
* initialized to NULL.
*
* For opaque types, a buffer is allocated using malloc(3C) to hold the
* opaque data. A pointer to this buffer and its size are stored in
* the caller-provided scf_opaque_t. It is the caller's responsibility
* to free this buffer. To simplify error handling, the address fields
* for unread opaque data are initialized to NULL.
*
* All other data is stored directly in caller-provided variables or
* structures.
*
* If this function fails to read a specific property, *badprop is set
* to point at that property's entry in the properties array.
*
* On all failures, all memory allocated by this function is freed.
*/
int
{
scf_service_t *s = scf_service_create(h);
scf_instance_t *i = scf_instance_create(h);
scf_property_t *p = scf_property_create(h);
scf_value_t *v = scf_value_create(h);
int error = 0;
goto scferror;
goto scferror;
if (scf_error() != SCF_ERROR_NOT_SET)
goto scferror;
}
if (running) {
if (!instance) {
goto out;
}
goto scferror;
}
goto scferror;
}
int ret = 0;
scf_property_get_value(p, v) == -1) {
goto scferror;
}
case SCF_TYPE_BOOLEAN: {
uint8_t b;
ret = scf_value_get_boolean(v, &b);
if (ret == -1)
break;
} else {
}
break;
}
case SCF_TYPE_COUNT:
break;
case SCF_TYPE_INTEGER:
break;
case SCF_TYPE_TIME: {
break;
}
case SCF_TYPE_OPAQUE: {
if (size == -1) {
goto scferror;
}
goto out;
}
break;
}
default: {
char *s;
if (size == -1) {
goto scferror;
}
goto out;
}
}
if (ret == -1) {
goto scferror;
}
}
}
goto out;
out:
if (error != 0) {
(void) scf_set_error(error);
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
/*
*
* If this function fails to write a specific property, *badprop is set
* to point at that property's entry in the properties array.
*
* One significant difference between this function and the
* scf_read_propvec function is that for string types, pv_ptr is a
* char *, not a char **. This means that you can't write a propvec
* you just read, but makes other uses (hopefully the majority) simpler.
*/
int
{
scf_service_t *s = scf_service_create(h);
scf_property_t *p = scf_property_create(h);
scf_value_t **v = NULL;
scf_transaction_entry_t **e = NULL;
int i, n;
n = count_props(properties);
v = calloc(n, sizeof (scf_value_t *));
e = calloc(n, sizeof (scf_transaction_entry_t *));
goto out;
}
goto scferror;
for (i = 0; i < n; i++) {
v[i] = scf_value_create(h);
e[i] = scf_entry_create(h);
goto scferror;
}
!= SCF_SUCCESS)
goto scferror;
if (scf_error() != SCF_ERROR_NOT_SET)
goto scferror;
}
goto scferror;
top:
goto scferror;
if (ret == -1) {
goto scferror;
}
case SCF_TYPE_BOOLEAN: {
scf_value_set_boolean(v[i], b ? 1 : 0);
break;
}
case SCF_TYPE_COUNT:
break;
case SCF_TYPE_INTEGER:
break;
case SCF_TYPE_TIME: {
break;
}
case SCF_TYPE_OPAQUE: {
break;
}
case SCF_TYPE_ASTRING:
ret = scf_value_set_astring(v[i],
break;
default:
}
goto scferror;
}
}
if (ret == 1)
goto out;
goto top;
}
out:
if (v != NULL) {
for (i = 0; i < n; i++)
scf_value_destroy(v[i]);
free(v);
}
if (e != NULL) {
for (i = 0; i < n; i++)
scf_entry_destroy(e[i]);
free(e);
}
if (error != 0) {
(void) scf_set_error(error);
return (SCF_FAILED);
}
return (SCF_SUCCESS);
}
/*
* Returns
* 0 - success
* ECONNABORTED - repository connection broken
* ECANCELED - inst was deleted
* EPERM
* EACCES
* EROFS
* ENOMEM
*/
int
const char *pname)
{
scf_handle_t *h;
h = scf_instance_handle(inst);
return (ENOMEM);
}
switch (error) {
case SCF_ERROR_NOT_FOUND:
return (SCF_SUCCESS);
case SCF_ERROR_DELETED:
return (ECANCELED);
default:
return (ECONNABORTED);
case SCF_ERROR_NOT_SET:
}
}
tx = scf_transaction_create(h);
e = scf_entry_create(h);
goto out;
}
for (;;) {
goto scferror;
}
goto scferror;
}
ret = 0;
goto out;
}
if (r == -1) {
goto scferror;
}
goto scferror;
}
}
switch (scf_error()) {
case SCF_ERROR_DELETED:
case SCF_ERROR_NOT_FOUND:
ret = 0;
break;
break;
case SCF_ERROR_BACKEND_ACCESS:
break;
break;
default:
ret = ECONNABORTED;
break;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
}
out:
return (ret);
}
/*
* Check the "application/auto_enable" property for the passed FMRI.
* scf_simple_prop_get() should find the property on an instance
* or on the service FMRI. The routine returns:
* -1: inconclusive (likely no such property or FMRI)
* 0: auto_enable is false
* 1: auto_enable is true
*/
static int
is_auto_enabled(char *fmri)
{
int retval = -1;
"auto_enable");
if (!prop)
return (retval);
return (retval);
}
/*
* Check an array of services and enable any that don't have the
* "application/auto_enable" property set to "false", which is
* the interface to turn off this behaviour (see PSARC 2004/739).
*/
void
_check_services(char **svcs)
{
char *s;
if (is_auto_enabled(*svcs) == 0)
continue;
if (strcmp(SCF_STATE_STRING_DISABLED, s) == 0)
(void) smf_enable_instance(*svcs,
free(s);
}
}
}
/*ARGSUSED*/
static int
{
}
static int
{
}
{
if (l == 0)
else
return (SCF_STATE_UNINIT);
return (SCF_STATE_MAINT);
return (SCF_STATE_OFFLINE);
return (SCF_STATE_DISABLED);
return (SCF_STATE_ONLINE);
return (SCF_STATE_DEGRADED);
return (SCF_STATE_ALL);
else
return (-1);
}
/*
* int32_t smf_state_from_string()
* return the value of the macro SCF_STATE_* for the corresponding state
* it returns SCF_STATE_ALL if "all" is passed. -1 if the string passed doesn't
* correspond to any valid state.
*/
smf_state_from_string(const char *state)
{
return (state_from_string(state, 0));
}
/*
* smf_state_to_string()
* Takes an int32_t representing an SMF state and returns
* the corresponding string. The string is read only and need not to be
* freed.
* returns NULL on invalid input.
*/
const char *
{
switch (s) {
case SCF_STATE_UNINIT:
return (SCF_STATE_STRING_UNINIT);
case SCF_STATE_MAINT:
return (SCF_STATE_STRING_MAINT);
case SCF_STATE_OFFLINE:
return (SCF_STATE_STRING_OFFLINE);
case SCF_STATE_DISABLED:
return (SCF_STATE_STRING_DISABLED);
case SCF_STATE_ONLINE:
return (SCF_STATE_STRING_ONLINE);
case SCF_STATE_DEGRADED:
return (SCF_STATE_STRING_DEGRADED);
case SCF_STATE_ALL:
return ("all");
default:
return (NULL);
}
}