svccfg_internal.c revision 9e9ae1fc5a2cf0c35d578ad826dff4763cd0a605
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <assert.h>
#include <errno.h>
#include <libintl.h>
#include <libuutil.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include "svccfg.h"
/*
* Internal representation manipulation routines for svccfg(1)
*/
static uu_list_pool_t *entity_pool;
static uu_list_pool_t *pgroup_pool;
static uu_list_pool_t *property_pool;
static uu_list_pool_t *value_pool;
/* ARGSUSED */
static int
entity_cmp(const void *a, const void *b, void *p)
{
}
/*ARGSUSED*/
static int
pgroup_cmp(const void *a, const void *b, void *p)
{
}
/* ARGSUSED */
static int
property_cmp(const void *a, const void *b, void *p)
{
property_t *A = (property_t *)a;
property_t *B = (property_t *)b;
}
/* ARGSUSED */
int
value_cmp(const void *a, const void *b, void *p)
{
const value_t *A = a;
const value_t *B = b;
switch (A->sc_type) {
case SCF_TYPE_BOOLEAN:
case SCF_TYPE_COUNT:
case SCF_TYPE_INTEGER:
default:
}
}
void
{
uu_strerror(uu_error()));
NULL)
gettext("property group list pool creation failed: %s\n"),
uu_strerror(uu_error()));
0)) == NULL)
uu_strerror(uu_error()));
NULL)
gettext("property value list pool creation failed: %s\n"),
uu_strerror(uu_error()));
}
/*ARGSUSED*/
static int
internal_value_dump(void *v, void *pvt)
{
case SCF_TYPE_BOOLEAN:
(void) printf(" value = %s\n",
break;
case SCF_TYPE_COUNT:
break;
case SCF_TYPE_INTEGER:
break;
case SCF_TYPE_ASTRING:
case SCF_TYPE_FMRI:
case SCF_TYPE_HOST:
case SCF_TYPE_HOSTNAME:
case SCF_TYPE_NET_ADDR_V4:
case SCF_TYPE_NET_ADDR_V6:
case SCF_TYPE_OPAQUE:
case SCF_TYPE_TIME:
case SCF_TYPE_URI:
case SCF_TYPE_USTRING:
(void) printf(" value = %s\n",
break;
default:
break;
}
return (UU_WALK_NEXT);
}
/*ARGSUSED*/
static int
internal_property_dump(void *v, void *pvt)
{
property_t *p = v;
NULL, UU_DEFAULT);
return (UU_WALK_NEXT);
}
/*ARGSUSED*/
static int
internal_pgroup_dump(void *v, void *pvt)
{
NULL, UU_DEFAULT);
return (UU_WALK_NEXT);
}
/*ARGSUSED*/
static int
internal_instance_dump(void *v, void *pvt)
{
entity_t *i = v;
return (UU_WALK_NEXT);
}
/*ARGSUSED*/
static int
internal_service_dump(void *v, void *pvt)
{
entity_t *s = v;
return (UU_WALK_NEXT);
}
void
{
NULL, UU_DEFAULT);
}
bundle_t *
{
bundle_t *b;
return (b);
}
void
{
NULL)
free(b);
}
entity_t *
internal_service_new(const char *name)
{
entity_t *s;
0);
return (s);
}
void
{
void *cookie;
free(s);
}
entity_t *
internal_instance_new(const char *name)
{
entity_t *i;
/* Can't set i->sc_fmri until we're attached to a service. */
return (i);
}
void
{
free(i);
}
entity_t *
{
entity_t *t;
return (t);
}
pgroup_t *
{
pgroup_t *p;
p->sc_pgroup_name = "<unset>";
p->sc_pgroup_type = "<unset>";
return (p);
}
void
{
}
static pgroup_t *
{
continue;
return (pg);
return (pg);
}
return (NULL);
}
pgroup_t *
{
}
pgroup_t *
{
}
pgroup_t *
{
return (pg);
pg = internal_pgroup_new();
(void) internal_attach_pgroup(e, pg);
pg->sc_pgroup_flags = 0;
return (pg);
}
{
property_t *p;
p->sc_property_name = "<unset>";
return (p);
}
void
{
NULL) {
}
free(p);
}
{
property_t *p;
p != NULL;
return (p);
return (NULL);
}
value_t *
{
value_t *v;
return (v);
}
static void
{
}
{
property_t *p;
value_t *v;
p = internal_property_new();
p->sc_property_name = (char *)name;
p->sc_value_type = vtype;
v = internal_value_new();
switch (vtype) {
case SCF_TYPE_BOOLEAN:
case SCF_TYPE_COUNT:
break;
case SCF_TYPE_INTEGER:
break;
case SCF_TYPE_ASTRING:
case SCF_TYPE_FMRI:
case SCF_TYPE_HOST:
case SCF_TYPE_HOSTNAME:
case SCF_TYPE_NET_ADDR_V4:
case SCF_TYPE_NET_ADDR_V6:
case SCF_TYPE_OPAQUE:
case SCF_TYPE_TIME:
case SCF_TYPE_URI:
case SCF_TYPE_USTRING:
break;
default:
break;
}
internal_attach_value(p, v);
}
return (p);
}
/*
* Some of these attach functions use uu_list_append() to maintain the
* anyway, or the order is irrelevant.
*/
int
{
return (-1);
}
return (0);
}
int
{
return (0);
}
return (-1);
}
return (0);
}
int
{
return (-1);
}
return (0);
}
int
{
return (-1);
}
return (0);
}
/*
* Returns
* 0 - success
* -1 - prop already exists in pgrp
*/
int
{
return (-1);
}
return (0);
}
void
{
}
/*
* These functions create an internal representation of a property group
* (pgroup_t) from the repository (scf_propertygroup_t). They are used by the
* import functions in svccfg_libscf.c .
*
* load_init() must be called first to initialize these globals, and
* load_fini() should be called afterwards to destroy them.
*/
static size_t loadbuf_sz;
/*
* Initialize the global state for the load_*() routines.
* Returns
* 0 - success
* ENOMEM - out of memory
*/
int
load_init(void)
{
return (ENOMEM);
load_fini();
return (ENOMEM);
}
return (0);
}
void
load_fini(void)
{
load_valiter = NULL;
}
/*
* Create a property_t which represents an scf_property_t. Returns
* 0 - success
* ECANCELED - prop's pg was deleted
* ECONNABORTED - repository disconnected
* ENOMEM - out of memory
*/
static int
{
int r;
/* get name */
switch (scf_error()) {
case SCF_ERROR_DELETED:
return (ECANCELED);
return (ECONNABORTED);
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
default:
}
}
return (ENOMEM);
}
/* get type */
switch (scf_error()) {
case SCF_ERROR_DELETED:
r = ECANCELED;
goto out;
r = ECONNABORTED;
goto out;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
default:
}
}
/* get values */
switch (scf_error()) {
case SCF_ERROR_DELETED:
r = ECANCELED;
goto out;
r = ECONNABORTED;
goto out;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
default:
}
}
for (;;) {
if (r == 0)
break;
if (r != 1) {
switch (scf_error()) {
case SCF_ERROR_DELETED:
r = ECANCELED;
goto out;
r = ECONNABORTED;
goto out;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
default:
}
}
ival = internal_value_new();
case SCF_TYPE_BOOLEAN: {
uint8_t b;
r = scf_value_get_boolean(load_val, &b);
if (r != 0)
break;
}
case SCF_TYPE_COUNT:
if (r != 0)
break;
case SCF_TYPE_INTEGER:
if (r != 0)
break;
default:
if (ssz < 0)
bad_error("scf_value_get_as_string",
scf_error());
r = ENOMEM;
goto out;
}
}
}
return (0);
out:
return (r);
}
/*
* Returns
* 0 - success
* ECANCELED - pg was deleted
* ECONNABORTED - repository disconnected
* ENOMEM - out of memory
*/
int
{
ipg = internal_pgroup_new();
switch (scf_error()) {
case SCF_ERROR_DELETED:
return (ECANCELED);
return (ECONNABORTED);
case SCF_ERROR_NOT_SET:
case SCF_ERROR_NOT_BOUND:
default:
}
}
switch (scf_error()) {
case SCF_ERROR_DELETED:
return (ECANCELED);
return (ECONNABORTED);
case SCF_ERROR_NOT_SET:
case SCF_ERROR_NOT_BOUND:
default:
}
}
return (ENOMEM);
}
switch (scf_error()) {
case SCF_ERROR_DELETED:
return (ECANCELED);
return (ECONNABORTED);
case SCF_ERROR_NOT_SET:
case SCF_ERROR_NOT_BOUND:
default:
}
}
return (ENOMEM);
}
return (0);
}
/*
* Load a property group into a pgroup_t. Returns
* 0 - success
* ECANCELED - pg was deleted
* ECONNABORTED - repository disconnected
* EBADF - pg is corrupt (error printed if fmri is given)
* ENOMEM - out of memory
*/
int
const char *snapname)
{
int r;
switch (scf_error()) {
case SCF_ERROR_DELETED:
return (ECANCELED);
return (ECONNABORTED);
case SCF_ERROR_NOT_SET:
case SCF_ERROR_NOT_BOUND:
default:
}
}
switch (r) {
case 0:
break;
case ECANCELED:
case ECONNABORTED:
case ENOMEM:
return (r);
default:
bad_error("load_pg_attrs", r);
}
for (;;) {
if (r == 0)
break;
if (r != 1) {
switch (scf_error()) {
case SCF_ERROR_DELETED:
r = ECANCELED;
goto out;
r = ECONNABORTED;
goto out;
case SCF_ERROR_NOT_BOUND:
case SCF_ERROR_NOT_SET:
default:
bad_error("scf_iter_next_property",
scf_error());
}
}
switch (r) {
case 0:
break;
case ECANCELED:
case ECONNABORTED:
case ENOMEM:
goto out;
default:
bad_error("load_property", r);
}
if (r != 0) {
"%s has multiple definitions of "
"property \"%s\".\n"),
else
"the \"%s\" snapshot of %s has "
"multiple definitions of property "
"\"%s\".\n"),
}
r = EBADF;
goto out;
}
}
return (0);
out:
return (r);
}
/*
* These functions compare internal property groups and properties (pgroup_t
* & property_t). They return 1 if the given structures are equal and
* 0 otherwise. Some will report the differences between the two structures.
* They are used by the import functions in svccfg_libscf.c .
*/
int
int new)
{
"(property \"%s/%s\" has different values).\n");
"(new property \"%s/%s\" has different values).\n");
/*
* If we find any differences, we'll report conflicts. But
* conflict messages won't make any sense if the names don't
* match. If the caller supplied fmri, assert that the names
* match.
*/
} else {
return (0);
}
if (new)
"(new property \"%s/%s\" has different "
else
"(property \"%s/%s\" has different "
}
return (0);
}
return (0);
}
return (0);
}
}
return (1);
}
int
int new)
{
return (0);
}
if (fmri) {
if (new)
"(new property group \"%s\" has different "
else
"(property group \"%s\" has different "
}
return (0);
}
if (fmri) {
if (new)
"(new property group \"%s\" has different "
else
"(property group \"%s\" has different "
}
return (0);
}
return (1);
}
int
{
return (0);
return (0);
return (0);
}
return (1);
}