/* * Inputs: * lpg is the property group to look up * lprop is the property within that group to look up * Outputs: * answer is a pointer to the property value * Returns: * 0 on success * -1 on failure * If successful, the property value is retured in *answer. * Otherwise, *answer is undefined, and it is up to the caller to decide * how to handle that case. */ int lookup_count_property(const char *lpg, const char *lprop, uint64_t *answer) { int result = -1; scf_resources_t res; if (get_property_value(lpg, lprop, &res) != 0) { /* * an error was already logged by get_property_value, * and it released any resources assigned to res before * returning. */ return (result); } if (scf_value_get_count(res.sr_val, answer) != 0) { syslog(LOG_ERR, "scf_value_get_count() failed: %s", scf_strerror(scf_error())); goto cleanup; } dprintf("lookup_count_property(%s, %s) returns %lld", lpg, lprop, *answer); result = 0; cleanup: release_scf_resources(&res); return (result); }
/* * 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); }
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); }