/* * 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); }
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); }
/* * 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); }
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); }