/*
 * 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
 *   EACCES - permission denied when reading property
 */
static int
load_property(scf_property_t *prop, property_t **ipp)
{
	property_t *iprop;
	int r;
	ssize_t ssz;

	/* get name */
	if (scf_property_get_name(prop, loadbuf, loadbuf_sz) < 0) {
		switch (scf_error()) {
		case SCF_ERROR_DELETED:
			return (ECANCELED);

		case SCF_ERROR_CONNECTION_BROKEN:
			return (ECONNABORTED);

		case SCF_ERROR_NOT_BOUND:
		case SCF_ERROR_NOT_SET:
		default:
			bad_error("scf_property_get_name", scf_error());
		}
	}

	iprop = internal_property_new();
	iprop->sc_property_name = strdup(loadbuf);
	if (iprop->sc_property_name == NULL) {
		internal_property_free(iprop);
		return (ENOMEM);
	}

	/* get type */
	if (scf_property_type(prop, &iprop->sc_value_type) != 0) {
		switch (scf_error()) {
		case SCF_ERROR_DELETED:
			r = ECANCELED;
			goto out;

		case SCF_ERROR_CONNECTION_BROKEN:
			r = ECONNABORTED;
			goto out;

		case SCF_ERROR_NOT_BOUND:
		case SCF_ERROR_NOT_SET:
		default:
			bad_error("scf_property_type", scf_error());
		}
	}

	/* get values */
	if (scf_iter_property_values(load_valiter, prop) != 0) {
		switch (scf_error()) {
		case SCF_ERROR_DELETED:
			r = ECANCELED;
			goto out;

		case SCF_ERROR_CONNECTION_BROKEN:
			r = ECONNABORTED;
			goto out;

		case SCF_ERROR_HANDLE_MISMATCH:
		case SCF_ERROR_NOT_BOUND:
		case SCF_ERROR_NOT_SET:
		default:
			bad_error("scf_iter_property_values", scf_error());
		}
	}

	for (;;) {
		value_t *ival;

		r = scf_iter_next_value(load_valiter, load_val);
		if (r == 0)
			break;
		if (r != 1) {
			switch (scf_error()) {
			case SCF_ERROR_DELETED:
				r = ECANCELED;
				goto out;

			case SCF_ERROR_CONNECTION_BROKEN:
				r = ECONNABORTED;
				goto out;

			case SCF_ERROR_PERMISSION_DENIED:
				r = EACCES;
				goto out;

			case SCF_ERROR_HANDLE_MISMATCH:
			case SCF_ERROR_NOT_BOUND:
			case SCF_ERROR_NOT_SET:
			case SCF_ERROR_INVALID_ARGUMENT:
			default:
				bad_error("scf_iter_next_value", scf_error());
			}
		}

		ival = internal_value_new();
		ival->sc_type = scf_value_type(load_val);
		assert(ival->sc_type != SCF_TYPE_INVALID);

		switch (ival->sc_type) {
		case SCF_TYPE_BOOLEAN: {
			uint8_t b;

			r = scf_value_get_boolean(load_val, &b);
			if (r != 0)
				bad_error("scf_value_get_boolean", scf_error());
			ival->sc_u.sc_count = b;
			break;
		}

		case SCF_TYPE_COUNT:
			r = scf_value_get_count(load_val, &ival->sc_u.sc_count);
			if (r != 0)
				bad_error("scf_value_get_count", scf_error());
			break;

		case SCF_TYPE_INTEGER:
			r = scf_value_get_integer(load_val,
			    &ival->sc_u.sc_integer);
			if (r != 0)
				bad_error("scf_value_get_integer", scf_error());
			break;

		default:
			ssz = scf_value_get_as_string(load_val, loadbuf,
			    loadbuf_sz);
			if (ssz < 0)
				bad_error("scf_value_get_as_string",
				    scf_error());

			ival->sc_u.sc_string = strdup(loadbuf);
			if (ival->sc_u.sc_string == NULL) {
				r = ENOMEM;
				goto out;
			}

			ival->sc_free = internal_value_free_str;
		}

		internal_attach_value(iprop, ival);
	}

	*ipp = iprop;
	return (0);

out:
	free(iprop->sc_property_name);
	internal_property_free(iprop);
	return (r);
}
Example #2
0
conerr_t
smfu_set_property(char *fmri, char *pgname, char *propname, char *value)
{
	conerr_t err = ce_ok;
	scf_handle_t *scfhandle = handle_create();
	scf_service_t *service = scf_service_create(scfhandle);
	scf_instance_t *instance = scf_instance_create(scfhandle);
	scf_propertygroup_t *pg = scf_pg_create(scfhandle);
	scf_property_t *prop = scf_property_create(scfhandle);
	scf_value_t *val = scf_value_create(scfhandle);
	scf_transaction_t *tx = scf_transaction_create(scfhandle);
	scf_transaction_entry_t *ent = scf_entry_create(scfhandle);
	scf_type_t type;

	if (scfhandle == NULL || service == NULL || instance == NULL ||
	    pg == NULL || prop == NULL || tx == NULL || ent == NULL ||
	    val == NULL) {
		err = ce_nomem;
		goto out;
	}

	if (scf_handle_decode_fmri(scfhandle, fmri, NULL, service, instance,
	    NULL, NULL, 0) != SCF_SUCCESS) {
		rad_log(RL_ERROR, "couldn't decode '%s': %s\n", fmri,
		    scf_strerror(scf_error()));
		err = maperr(scf_error());
		goto out;
	}

	if (scf_instance_get_pg(instance, pgname, pg) != 0 ||
	    scf_pg_get_property(pg, propname, prop) != 0 ||
	    scf_property_type(prop, &type) != 0) {
		rad_log(RL_ERROR, "couldn't get property: '%s/%s/%s': %s\n",
		    fmri, pgname, propname, scf_strerror(scf_error()));
		err = maperr(scf_error());
		goto out;
	}

top:
	if (scf_transaction_start(tx, pg) == -1 ||
	    scf_transaction_property_change(tx, ent, propname, type) != 0 ||
	    scf_value_set_from_string(val, type, value) != 0 ||
	    scf_entry_add_value(ent, val) != 0) {
		rad_log(RL_ERROR, "couldn't set property: '%s/%s/%s': %s\n",
		    fmri, pgname, propname, scf_strerror(scf_error()));
		err = maperr(scf_error());
		goto out;
	}

	switch (scf_transaction_commit(tx)) {
	/* success */
	case 1:
		if (smf_refresh_instance(fmri) != 0) {
			err = maperr(scf_error());
			goto out;
		}
		break;
	/* retry */
	case 0:
		if (scf_pg_update(pg) != 0) {
			err = maperr(scf_error());
			goto out;
		}
		scf_transaction_reset(tx);
		goto top;
	default:
		err = maperr(scf_error());
		goto out;
	}
out:
	scf_entry_destroy(ent);
	scf_transaction_destroy(tx);
	scf_value_destroy(val);
	scf_property_destroy(prop);
	scf_pg_destroy(pg);
	scf_instance_destroy(instance);
	scf_service_destroy(service);
	scf_handle_destroy(scfhandle);

	return (err);
}
Example #3
0
/*
 * Display a property's values on a line.  If types is true, prepend
 * identification (the FMRI if fmris is true, pg/prop otherwise) and the type
 * of the property.
 */
static void
display_prop(scf_propertygroup_t *pg, scf_property_t *prop)
{
	scf_value_t *val;
	scf_iter_t *iter;
	int ret, first, err;

	const char * const permission_denied_emsg =
	    gettext("Permission denied.\n");

	if (types) {
		scf_type_t ty;
		char *buf;
		size_t buf_sz;

		if (fmris) {
			buf_sz = max_scf_fmri_length + 1;
			buf = safe_malloc(buf_sz);

			if (scf_property_to_fmri(prop, buf, buf_sz) == -1)
				scfdie();
			(void) fputs(buf, stdout);

			free(buf);
		} else {
			buf_sz = max_scf_name_length + 1;
			buf = safe_malloc(buf_sz);

			if (scf_pg_get_name(pg, buf, buf_sz) < 0)
				scfdie();
			(void) fputs(buf, stdout);
			(void) putchar('/');

			if (scf_property_get_name(prop, buf, buf_sz) < 0)
				scfdie();
			(void) fputs(buf, stdout);

			free(buf);
		}

		(void) putchar(' ');

		if (scf_property_type(prop, &ty) == -1)
			scfdie();
		(void) fputs(scf_type_to_string(ty), stdout);
		(void) putchar(' ');
	}

	if ((iter = scf_iter_create(hndl)) == NULL ||
	    (val = scf_value_create(hndl)) == NULL)
		scfdie();

	if (scf_iter_property_values(iter, prop) == -1)
		scfdie();

	first = 1;
	while ((ret = scf_iter_next_value(iter, val)) == 1) {
		if (first)
			first = 0;
		else
			(void) putchar(' ');
		print_value(val);
	}
	if (ret == -1) {
		err = scf_error();
		if (err == SCF_ERROR_PERMISSION_DENIED) {
			if (uu_list_numnodes(prop_list) > 0)
				die(permission_denied_emsg);
		} else {
			scfdie();
		}
	}

	(void) putchar('\n');

	scf_iter_destroy(iter);
	(void) scf_value_destroy(val);
}
Example #4
0
void
read_scf_proto_cfg(const char *proto, scf_cfg_t *cfg)
{
	scf_handle_t *handle = NULL;
	scf_scope_t *sc = NULL;
	scf_service_t *svc = NULL;
	scf_propertygroup_t *pg = NULL;
	scf_property_t *prop = NULL;
	scf_value_t *value = NULL;
	scf_iter_t *value_iter = NULL;
	uint64_t val;
	char *str;
	size_t slen;
	int i;

	handle = scf_handle_create(SCF_VERSION);
	sc = scf_scope_create(handle);
	svc = scf_service_create(handle);
	pg = scf_pg_create(handle);
	prop = scf_property_create(handle);
	value = scf_value_create(handle);
	value_iter = scf_iter_create(handle);

	if (handle == NULL || sc == NULL || svc == NULL || pg == NULL ||
	    prop == NULL || value == NULL || value_iter == NULL) {
		DMSG(D_OP, "%s: unable to create smf(5) handles.", proto);
		goto done;
	}

	if (scf_handle_bind(handle) != 0) {
		DMSG(D_OP, "%s: unable to bind smf(5) handle: %s", proto,
		    scf_strerror(scf_error()));
		goto done;
	}

	if (scf_handle_decode_fmri(handle, fmri, sc, svc, NULL, NULL, NULL,
	    0) != 0) {
		DMSG(D_OP, "%s: unable to decode fmri '%s': %s", fmri,
		    scf_strerror(scf_error()));
		goto done;
	}

	if (scf_service_get_pg(svc, proto, pg) != 0 &&
	    scf_error() != SCF_ERROR_NOT_FOUND) {
		DMSG(D_OP, "%s: unable to read '%s' property group: %s",
		    proto, proto, scf_strerror(scf_error()));
		goto done;
	}

	for (i = 0; cfg[i].name != NULL; i++) {
		scf_cfg_t *c = &cfg[i];

		if (scf_pg_get_property(pg, c->name, prop) != 0) {
			if (scf_error() != SCF_ERROR_NOT_FOUND)
				DMSG(D_OP, "%s: unable to read %s/%s from "
				    "smf: %s", proto, proto, c->name,
				    scf_strerror(scf_error()));

			continue;
		}

		if (scf_property_is_type(prop, c->type) != 0) {
			scf_type_t type;

			if (scf_error() != SCF_ERROR_TYPE_MISMATCH) {
				DMSG(D_OP, "%s: unable to validate "
				    "type of '%s/%s' smf property: %s",
				    proto, proto, c->name,
				    scf_strerror(scf_error()));
				continue;
			}

			if (scf_property_type(prop, &type) != 0) {
				DMSG(D_OP, "%s: unable to obtain "
				    "type of '%s/%s' smf property: %s",
				    proto, proto, c->name,
				    scf_strerror(scf_error()));
				continue;
			}

			DMSG(D_OP, "%s: property '%s/%s' has an unexpected "
			    "type:\n"
			    "   expected type: %s\n"
			    "     actual type: %s\n",
			    proto, proto, c->name,
			    scf_type_to_string(c->type),
			    scf_type_to_string(type));
			continue;
		}

		if (scf_property_get_value(prop, value) != 0) {
			if (scf_error() != SCF_ERROR_NOT_SET)
				DMSG(D_OP, "%s: unable to get value of "
				    "'%s/%s' smf property: %s", proto,
				    proto, c->name, scf_strerror(scf_error()));

			continue;
		}

		switch (c->type) {
		case SCF_TYPE_COUNT:
			if (scf_value_get_count(value, &val) != 0) {
				DMSG(D_OP, "%s: unable to read value of "
				    "'%s/%s' smf property: %s", proto, proto,
				    c->name, scf_strerror(scf_error()));
				continue;
			}

			if (val > c->max) {
				DMSG(D_OP, "%s: value of '%s/%s' smf property "
				    "(%'llu) is out of range (0 - %'zu).",
				    proto, proto, c->name, val, c->max);
				continue;
			}
			*((uint32_t *)c->val) = (uint32_t)val;
			break;
		case SCF_TYPE_ASTRING:
		{
			char **valp = (char **)c->val;
			ssize_t len;

			slen = c->max + 1;
			if ((str = malloc(slen)) == NULL) {
				/* XXX message */
				continue;
			}
			if ((len = scf_value_get_astring(value, str,
			    slen)) >= slen)
				DMSG(D_OP, "%s: length of '%s/%s' "
				    "(%'zd bytes) exceeds maximum "
				    "allowable length (%zu bytes).  The string"
				    " will be truncated.", proto, proto,
				    c->name, len, c->max);

			free(*valp);
			*valp = str;
			break;
		}
		default:
			VERIFY(0);
		}
	}

done:
	scf_iter_destroy(value_iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	scf_pg_destroy(pg);
	scf_service_destroy(svc);
	scf_scope_destroy(sc);
	scf_handle_destroy(handle);
}