int topo_fmri_serial(topo_hdl_t *thp, nvlist_t *nvl, char **serial, int *err) { nvlist_t *prop = NULL; char *sp; /* * If there is a serial id in the resource fmri, then use that. * Otherwise fall back to looking for a serial id property in the * protocol group. */ if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, &sp) == 0) { if ((*serial = topo_hdl_strdup(thp, sp)) == NULL) return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_serial", prop)); else return (0); } if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, FM_FMRI_HC_SERIAL_ID, NULL, &prop, err) < 0) return (set_error(thp, *err, err, "topo_fmri_serial", NULL)); if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &sp) != 0) return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_serial", prop)); if ((*serial = topo_hdl_strdup(thp, sp)) == NULL) return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_serial", prop)); nvlist_free(prop); return (0); }
/* * Fetch the Facility Node properties (name, type) from the FMRI * for this node, or return -1 if we can't. */ static int get_facility_props(topo_hdl_t *hdl, tnode_t *node, char **facname, char **factype) { int e, ret = -1; nvlist_t *fmri = NULL, *fnvl; char *nn = NULL, *tt = NULL; if (topo_node_resource(node, &fmri, &e) != 0) goto out; if (nvlist_lookup_nvlist(fmri, FM_FMRI_FACILITY, &fnvl) != 0) goto out; if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_NAME, &nn) != 0) goto out; if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_TYPE, &tt) != 0) goto out; *facname = topo_hdl_strdup(hdl, nn); *factype = topo_hdl_strdup(hdl, tt); ret = 0; out: nvlist_free(fmri); return (ret); }
int topo_fmri_nvl2str(topo_hdl_t *thp, nvlist_t *fmri, char **fmristr, int *err) { char *scheme, *str; nvlist_t *out = NULL; tnode_t *rnode; if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0) return (set_error(thp, ETOPO_FMRI_MALFORM, err, TOPO_METH_NVL2STR, out)); if ((rnode = topo_hdl_root(thp, scheme)) == NULL) return (set_error(thp, ETOPO_METHOD_NOTSUP, err, TOPO_METH_NVL2STR, out)); if (topo_method_invoke(rnode, TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_VERSION, fmri, &out, err) != 0) return (set_error(thp, *err, err, TOPO_METH_NVL2STR, out)); if (out == NULL || nvlist_lookup_string(out, "fmri-string", &str) != 0) return (set_error(thp, ETOPO_METHOD_INVAL, err, TOPO_METH_NVL2STR, out)); if ((*fmristr = topo_hdl_strdup(thp, str)) == NULL) return (set_error(thp, ETOPO_NOMEM, err, TOPO_METH_NVL2STR, out)); nvlist_free(out); return (0); }
int prop_method_register(tnode_t *node, const char *pgname, const char *pname, topo_type_t ptype, const char *mname, topo_version_t version, const nvlist_t *args, int *err) { topo_hdl_t *thp = node->tn_hdl; topo_propmethod_t *pm = NULL; topo_propval_t *pv = NULL; if ((pm = topo_hdl_zalloc(thp, sizeof (topo_propmethod_t))) == NULL) return (register_methoderror(node, pm, err, 1, ETOPO_PROP_NOMEM)); if ((pm->tpm_name = topo_hdl_strdup(thp, mname)) == NULL) return (register_methoderror(node, pm, err, 1, ETOPO_PROP_NOMEM)); pm->tpm_version = version; if (topo_hdl_nvdup(thp, (nvlist_t *)args, &pm->tpm_args) != 0) return (register_methoderror(node, pm, err, 1, ETOPO_PROP_NOMEM)); /* * It's possible the property may already exist. However we still want * to allow the method to be registered. This is to handle the case * where we specify a prop method in an xml map to override the value * that was set by the enumerator. * * By default, propmethod-backed properties are not MUTABLE. This is * done to simplify the programming model for modules that implement * property methods as most propmethods tend to only support get * operations. Enumerator modules can override this by calling * topo_prop_setmutable(). Propmethods that are registered via XML can * be set as mutable via the optional "mutable" attribute, which will * result in the xml parser calling topo_prop_setflags() after * registering the propmethod. */ if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) if ((pv = prop_create(node, pgname, pname, ptype, TOPO_PROP_IMMUTABLE, err)) == NULL) { /* node unlocked */ return (register_methoderror(node, pm, err, 0, *err)); } if (pv->tp_method != NULL) return (register_methoderror(node, pm, err, 1, ETOPO_METHOD_DEFD)); if (pv->tp_val != NULL) { nvlist_free(pv->tp_val); pv->tp_val = NULL; } pv->tp_method = pm; topo_node_unlock(node); return (0); }
static topo_propval_t * prop_create(tnode_t *node, const char *pgname, const char *pname, topo_type_t type, int flag, int *err) { topo_hdl_t *thp = node->tn_hdl; topo_pgroup_t *pg; topo_propval_t *pv; topo_proplist_t *pvl; /* * Replace existing prop value with new one */ if ((pg = pgroup_get(node, pgname)) == NULL) { topo_node_unlock(node); *err = ETOPO_PROP_NOENT; return (NULL); } if ((pv = propval_get(pg, pname)) != NULL) { if (pv->tp_type != type) return (set_seterror(node, NULL, err, ETOPO_PROP_TYPE)); else if (! (pv->tp_flag & TOPO_PROP_MUTABLE)) return (set_seterror(node, NULL, err, ETOPO_PROP_DEFD)); nvlist_free(pv->tp_val); pv->tp_val = NULL; } else { if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t))) == NULL) return (set_seterror(node, NULL, err, ETOPO_NOMEM)); if ((pv = topo_hdl_zalloc(thp, sizeof (topo_propval_t))) == NULL) return (set_seterror(node, pvl, err, ETOPO_NOMEM)); pv->tp_hdl = thp; pvl->tp_pval = pv; if ((pv->tp_name = topo_hdl_strdup(thp, pname)) == NULL) return (set_seterror(node, pvl, err, ETOPO_NOMEM)); pv->tp_flag = flag; pv->tp_type = type; topo_prop_hold(pv); topo_list_append(&pg->tpg_pvals, pvl); } return (pv); }
int topo_pgroup_create(tnode_t *node, const topo_pgroup_info_t *pinfo, int *err) { topo_pgroup_t *pg; topo_ipgroup_info_t *pip; topo_hdl_t *thp = node->tn_hdl; *err = 0; topo_node_lock(node); /* * Check for an existing pgroup */ for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pg->tpg_info->tpi_name, pinfo->tpi_name) == 0) { *err = ETOPO_PROP_DEFD; topo_node_unlock(node); return (-1); } } if ((pg = topo_hdl_zalloc(thp, sizeof (topo_pgroup_t))) == NULL) { *err = ETOPO_NOMEM; topo_node_unlock(node); return (-1); } if ((pip = topo_hdl_zalloc(thp, sizeof (topo_ipgroup_info_t))) == NULL) return (pgroup_seterr(node, pg, pip, err)); if ((pip->tpi_name = topo_hdl_strdup(thp, pinfo->tpi_name)) == NULL) return (pgroup_seterr(node, pg, pip, err)); pip->tpi_namestab = pinfo->tpi_namestab; pip->tpi_datastab = pinfo->tpi_datastab; pip->tpi_version = pinfo->tpi_version; pg->tpg_info = pip; topo_list_append(&node->tn_pgroups, pg); topo_node_unlock(node); return (0); }
int topo_fmri_label(topo_hdl_t *thp, nvlist_t *nvl, char **label, int *err) { nvlist_t *prop = NULL; char *lp; if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL, NULL, &prop, err) < 0) return (set_error(thp, *err, err, "topo_fmri_label", NULL)); if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &lp) != 0) return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_label", prop)); if ((*label = topo_hdl_strdup(thp, lp)) == NULL) return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_label", prop)); nvlist_free(prop); return (0); }
topo_pgroup_info_t * topo_pgroup_info(tnode_t *node, const char *pgname, int *err) { topo_hdl_t *thp = node->tn_hdl; topo_pgroup_t *pg; topo_ipgroup_info_t *pip; topo_pgroup_info_t *info; topo_node_lock(node); for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pgname, pg->tpg_info->tpi_name) == 0) { if ((info = topo_hdl_alloc(thp, sizeof (topo_pgroup_info_t))) == NULL) return (NULL); pip = pg->tpg_info; if ((info->tpi_name = topo_hdl_strdup(thp, pip->tpi_name)) == NULL) { *err = ETOPO_PROP_NOMEM; topo_hdl_free(thp, info, sizeof (topo_pgroup_info_t)); topo_node_unlock(node); return (NULL); } info->tpi_namestab = pip->tpi_namestab; info->tpi_datastab = pip->tpi_datastab; info->tpi_version = pip->tpi_version; topo_node_unlock(node); return (info); } } *err = ETOPO_PROP_NOENT; topo_node_unlock(node); return (NULL); }
static int prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val, topo_type_t type, uint_t *nelems, int *err) { int i, j, ret = 0; topo_hdl_t *thp = node->tn_hdl; topo_propval_t *pv; topo_node_lock(node); if ((pv = prop_get(node, pgname, pname, NULL, err)) == NULL) return (get_properror(node, err, *err)); if (pv->tp_type != type) return (get_properror(node, err, ETOPO_PROP_TYPE)); switch (type) { case TOPO_TYPE_INT32: ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL, (int32_t *)val); break; case TOPO_TYPE_UINT32: ret = nvlist_lookup_uint32(pv->tp_val, TOPO_PROP_VAL_VAL, (uint32_t *)val); break; case TOPO_TYPE_INT64: ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL, (int64_t *)val); break; case TOPO_TYPE_UINT64: ret = nvlist_lookup_uint64(pv->tp_val, TOPO_PROP_VAL_VAL, (uint64_t *)val); break; case TOPO_TYPE_DOUBLE: ret = nvlist_lookup_double(pv->tp_val, TOPO_PROP_VAL_VAL, (double *)val); break; case TOPO_TYPE_STRING: { char *str; ret = nvlist_lookup_string(pv->tp_val, TOPO_PROP_VAL_VAL, &str); if (ret == 0) { char *s2; if ((s2 = topo_hdl_strdup(thp, str)) == NULL) ret = -1; else *(char **)val = s2; } break; } case TOPO_TYPE_FMRI: { nvlist_t *nvl; ret = nvlist_lookup_nvlist(pv->tp_val, TOPO_PROP_VAL_VAL, &nvl); if (ret == 0) ret = topo_hdl_nvdup(thp, nvl, (nvlist_t **)val); break; } case TOPO_TYPE_INT32_ARRAY: { int32_t *a1, *a2; if ((ret = nvlist_lookup_int32_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(int32_t **)val = a1; break; } case TOPO_TYPE_UINT32_ARRAY: { uint32_t *a1, *a2; if ((ret = nvlist_lookup_uint32_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(uint32_t **)val = a1; break; } case TOPO_TYPE_INT64_ARRAY: { int64_t *a1, *a2; if ((ret = nvlist_lookup_int64_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(int64_t **)val = a1; break; } case TOPO_TYPE_UINT64_ARRAY: { uint64_t *a1, *a2; if ((ret = nvlist_lookup_uint64_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(uint64_t **)val = a1; break; } case TOPO_TYPE_STRING_ARRAY: { char **a1, **a2; if ((ret = nvlist_lookup_string_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (char *) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) { if ((a1[i] = topo_hdl_strdup(thp, a2[i])) == NULL) { for (j = 0; j < i; ++j) topo_hdl_free(thp, a1[j], sizeof (char *)); topo_hdl_free(thp, a1, sizeof (char *) * *nelems); break; } } *(char ***)val = a1; break; } case TOPO_TYPE_FMRI_ARRAY: { nvlist_t **a1, **a2; if ((ret = nvlist_lookup_nvlist_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) { if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) { for (j = 0; j < i; ++j) nvlist_free(a1[j]); topo_hdl_free(thp, a1, sizeof (nvlist_t *) * *nelems); break; } } *(nvlist_t ***)val = a1; break; } default: ret = ETOPO_PROP_NOENT; } if (ret != 0) if (ret == ENOENT) return (get_properror(node, err, ETOPO_PROP_NOENT)); else if (ret < ETOPO_UNKNOWN) return (get_properror(node, err, ETOPO_PROP_NVL)); else return (get_properror(node, err, ret)); topo_node_unlock(node); return (0); }
static char * topo_snap_create(topo_hdl_t *thp, int *errp, boolean_t need_force) { uuid_t uuid; char *ustr = NULL; topo_hdl_lock(thp); if (thp->th_uuid != NULL) { *errp = ETOPO_HDL_UUID; topo_hdl_unlock(thp); return (NULL); } if ((thp->th_uuid = topo_hdl_zalloc(thp, TOPO_UUID_SIZE)) == NULL) { *errp = ETOPO_NOMEM; topo_dprintf(thp, TOPO_DBG_ERR, "unable to allocate uuid: %s\n", topo_strerror(*errp)); topo_hdl_unlock(thp); return (NULL); } uuid_generate(uuid); uuid_unparse(uuid, thp->th_uuid); if ((ustr = topo_hdl_strdup(thp, thp->th_uuid)) == NULL) { *errp = ETOPO_NOMEM; topo_hdl_unlock(thp); return (NULL); } if (need_force) { topo_dprintf(thp, TOPO_DBG_FORCE, "taking a DINFOFORCE snapshot\n"); thp->th_di = di_init("/", DINFOFORCE | DINFOSUBTREE | DINFOMINOR | DINFOPROP | DINFOPATH); } else { thp->th_di = di_init("/", DINFOCACHE); } thp->th_pi = di_prom_init(); if (topo_tree_enum_all(thp) < 0) { topo_dprintf(thp, TOPO_DBG_ERR, "enumeration failure: %s\n", topo_hdl_errmsg(thp)); if (topo_hdl_errno(thp) == ETOPO_ENUM_FATAL) { *errp = thp->th_errno; if (thp->th_di != DI_NODE_NIL) { di_fini(thp->th_di); thp->th_di = DI_NODE_NIL; } if (thp->th_pi != DI_PROM_HANDLE_NIL) { di_prom_fini(thp->th_pi); thp->th_pi = DI_PROM_HANDLE_NIL; } topo_hdl_strfree(thp, ustr); topo_hdl_unlock(thp); return (NULL); } } if (thp->th_ipmi != NULL && ipmi_sdr_changed(thp->th_ipmi) && ipmi_sdr_refresh(thp->th_ipmi) != 0) { topo_dprintf(thp, TOPO_DBG_ERR, "failed to refresh IPMI sdr repository: %s\n", ipmi_errmsg(thp->th_ipmi)); } topo_hdl_unlock(thp); return (ustr); }
topo_hdl_t * topo_open(int version, const char *rootdir, int *errp) { topo_hdl_t *thp = NULL; topo_alloc_t *tap; char platform[MAXNAMELEN]; char isa[MAXNAMELEN]; struct utsname uts; struct stat st; smbios_hdl_t *shp; smbios_system_t s1; smbios_info_t s2; id_t id; char *dbflags, *dbout; if (version != TOPO_VERSION) return (set_open_errno(thp, errp, ETOPO_HDL_ABIVER)); if (rootdir != NULL && stat(rootdir, &st) < 0) return (set_open_errno(thp, errp, ETOPO_HDL_INVAL)); if ((thp = topo_zalloc(sizeof (topo_hdl_t), 0)) == NULL) return (set_open_errno(thp, errp, ETOPO_NOMEM)); (void) pthread_mutex_init(&thp->th_lock, NULL); if ((tap = topo_zalloc(sizeof (topo_alloc_t), 0)) == NULL) return (set_open_errno(thp, errp, ETOPO_NOMEM)); /* * Install default allocators */ tap->ta_flags = 0; tap->ta_alloc = topo_alloc; tap->ta_zalloc = topo_zalloc; tap->ta_free = topo_free; tap->ta_nvops.nv_ao_alloc = topo_nv_alloc; tap->ta_nvops.nv_ao_free = topo_nv_free; (void) nv_alloc_init(&tap->ta_nva, &tap->ta_nvops); thp->th_alloc = tap; if ((thp->th_modhash = topo_modhash_create(thp)) == NULL) return (set_open_errno(thp, errp, ETOPO_NOMEM)); /* * Set-up system information and search paths for modules * and topology map files */ if (rootdir == NULL) { rootdir = topo_hdl_strdup(thp, "/"); thp->th_rootdir = (char *)rootdir; } else { int len; char *rpath; len = strlen(rootdir); if (len >= PATH_MAX) return (set_open_errno(thp, errp, EINVAL)); if (rootdir[len - 1] != '/') { rpath = alloca(len + 2); (void) snprintf(rpath, len + 2, "%s/", rootdir); } else { rpath = (char *)rootdir; } thp->th_rootdir = topo_hdl_strdup(thp, rpath); } platform[0] = '\0'; isa[0] = '\0'; (void) sysinfo(SI_PLATFORM, platform, sizeof (platform)); (void) sysinfo(SI_ARCHITECTURE, isa, sizeof (isa)); (void) uname(&uts); thp->th_platform = topo_hdl_strdup(thp, platform); thp->th_isa = topo_hdl_strdup(thp, isa); thp->th_machine = topo_hdl_strdup(thp, uts.machine); if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) { if ((id = smbios_info_system(shp, &s1)) != SMB_ERR && smbios_info_common(shp, id, &s2) != SMB_ERR) { if (strcmp(s2.smbi_product, SMB_DEFAULT1) != 0 && strcmp(s2.smbi_product, SMB_DEFAULT2) != 0) { thp->th_product = topo_cleanup_auth_str(thp, (char *)s2.smbi_product); } } smbios_close(shp); } else { thp->th_product = topo_hdl_strdup(thp, thp->th_platform); } if (thp->th_rootdir == NULL || thp->th_platform == NULL || thp->th_machine == NULL) return (set_open_errno(thp, errp, ETOPO_NOMEM)); dbflags = getenv("TOPO_DEBUG"); dbout = getenv("TOPO_DEBUG_OUT"); if (dbflags != NULL) topo_debug_set(thp, dbflags, dbout); if (topo_builtin_create(thp, thp->th_rootdir) != 0) { topo_dprintf(thp, TOPO_DBG_ERR, "failed to load builtin modules: %s\n", topo_hdl_errmsg(thp)); return (set_open_errno(thp, errp, topo_hdl_errno(thp))); } return (thp); }