#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <dirent.h>
#include <libnvpair.h>
#include <dlfcn.h>
#include <unistd.h>
#include <errno.h>
#include <stropts.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/filio.h>
#include <sys/param.h>
#include <sys/fm/protocol.h>
#include <fm/fmd_api.h>
#include <fm/fmd_fmri.h>
#include <fm/libtopo.h>
#include <fm/topo_hc.h>
#include "alloc.h"
#include "out.h"
#include "tree.h"
#include "itree.h"
#include "ipath.h"
#include "ptree.h"
#include "fme.h"
#include "stable.h"
#include "eval.h"
#include "config.h"
#include "platform.h"
extern fmd_hdl_t *Hdl;
static struct cfgdata *Lastcfg;
static fmd_hdl_t *Lasthdl;
static fmd_case_t *Lastfmcase;
static const char *lastcomp;
static int in_getpath;
extern struct lut *Usednames;
int prune_raw_config = 0;
static topo_hdl_t *Eft_topo_hdl;
void *
topo_use_alloc(size_t bytes)
{
void *p = alloc_malloc(bytes, NULL, 0);
bzero(p, bytes);
return (p);
}
void
topo_use_free(void *p)
{
alloc_free(p, NULL, 0);
}
static void *
alloc_nv_alloc(nv_alloc_t *nva, size_t size)
{
return (alloc_malloc(size, NULL, 0));
}
static void
alloc_nv_free(nv_alloc_t *nva, void *p, size_t sz)
{
alloc_free(p, NULL, 0);
}
const nv_alloc_ops_t Eft_nv_alloc_ops = {
NULL,
NULL,
alloc_nv_alloc,
alloc_nv_free,
NULL
};
nv_alloc_t Eft_nv_hdl;
static char *Root;
static char *Mach;
static char *Plat;
static char tmpbuf[MAXPATHLEN];
static char numbuf[MAXPATHLEN];
static void
platform_globals()
{
Root = fmd_prop_get_string(Hdl, "fmd.rootdir");
Mach = fmd_prop_get_string(Hdl, "fmd.machine");
Plat = fmd_prop_get_string(Hdl, "fmd.platform");
}
static void
platform_free_globals()
{
fmd_prop_free_string(Hdl, Root);
fmd_prop_free_string(Hdl, Mach);
fmd_prop_free_string(Hdl, Plat);
}
void
platform_init(void)
{
(void) nv_alloc_init(&Eft_nv_hdl, &Eft_nv_alloc_ops);
Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
platform_globals();
out(O_ALTFP, "platform_init() sucessful");
}
void
platform_fini(void)
{
if (Lastcfg != NULL) {
config_free(Lastcfg);
Lastcfg = NULL;
}
fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
platform_free_globals();
(void) nv_alloc_fini(&Eft_nv_hdl);
out(O_ALTFP, "platform_fini() sucessful");
}
static struct node *
hc_fmri_nodeize(nvlist_t *hcfmri)
{
struct node *pathtree = NULL;
struct node *tmpn;
nvlist_t **hc_prs;
uint_t hc_nprs;
const char *sname;
char *ename;
char *eid;
int e, r;
if (nvlist_lookup_nvlist_array(hcfmri, FM_FMRI_HC_LIST,
&hc_prs, &hc_nprs) != 0) {
out(O_ALTFP, "XFILE: hc FMRI missing %s", FM_FMRI_HC_LIST);
return (NULL);
}
for (e = 0; e < hc_nprs; e++) {
ename = NULL;
eid = NULL;
r = nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_NAME, &ename);
r |= nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_ID, &eid);
if (r != 0) {
continue;
}
sname = stable(ename);
tmpn = tree_name_iterator(
tree_name(sname, IT_VERTICAL, NULL, 0),
tree_num(eid, NULL, 0));
if (pathtree == NULL)
pathtree = tmpn;
else
(void) tree_name_append(pathtree, tmpn);
}
return (pathtree);
}
struct node *
platform_getpath(nvlist_t *nvl)
{
struct node *ret;
nvlist_t *dfmri, *real_fmri, *resource;
char *scheme;
char *path;
char *devid;
char *tp;
uint32_t cpuid;
int err;
enum {DT_HC, DT_DEVID, DT_TP, DT_DEV, DT_CPU, DT_UNKNOWN} type =
DT_UNKNOWN;
if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &dfmri) != 0) {
out(O_ALTFP, "XFILE: ereport has no detector FMRI");
return (NULL);
}
if (nvlist_lookup_string(dfmri, FM_FMRI_SCHEME, &scheme) != 0) {
out(O_ALTFP, "XFILE: detector FMRI missing scheme");
return (NULL);
}
if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
type = DT_HC;
} else if (strcmp(scheme, FM_FMRI_SCHEME_DEV) == 0) {
if (nvlist_lookup_string(dfmri,
FM_FMRI_DEV_ID, &devid) == 0)
type = DT_DEVID;
else if (nvlist_lookup_string(dfmri,
TOPO_STORAGE_TARGET_PORT_L0ID, &tp) == 0)
type = DT_TP;
else if (nvlist_lookup_string(dfmri,
FM_FMRI_DEV_PATH, &path) == 0)
type = DT_DEV;
else {
out(O_ALTFP, "XFILE: detector FMRI missing %s or %s",
FM_FMRI_DEV_ID, FM_FMRI_DEV_PATH);
return (NULL);
}
} else if (strcmp(scheme, FM_FMRI_SCHEME_CPU) == 0) {
if (nvlist_lookup_uint32(dfmri, FM_FMRI_CPU_ID, &cpuid) == 0)
type = DT_CPU;
else {
out(O_ALTFP, "XFILE: detector FMRI missing %s",
FM_FMRI_CPU_ID);
return (NULL);
}
} else {
out(O_ALTFP, "XFILE: detector FMRI not recognized "
"(scheme is %s, expect %s or %s or %s)",
scheme, FM_FMRI_SCHEME_HC, FM_FMRI_SCHEME_DEV,
FM_FMRI_SCHEME_CPU);
return (NULL);
}
out(O_ALTFP|O_VERB, "Received ereport in scheme %s", scheme);
lut_free(Usednames, NULL, NULL);
Usednames = NULL;
in_getpath = 1;
if (config_snapshot() == NULL) {
if (type == DT_HC) {
in_getpath = 0;
return (hc_fmri_nodeize(dfmri));
}
out(O_ALTFP, "XFILE: cannot snapshot configuration");
in_getpath = 0;
return (NULL);
}
switch (type) {
case DT_HC:
if (topo_fmri_getprop(Eft_topo_hdl, dfmri, TOPO_PGROUP_PROTOCOL,
TOPO_PROP_RESOURCE, NULL, &resource, &err) == -1) {
ret = hc_fmri_nodeize(dfmri);
break;
} else if (nvlist_lookup_nvlist(resource,
TOPO_PROP_VAL_VAL, &real_fmri) != 0)
ret = hc_fmri_nodeize(dfmri);
else
ret = hc_fmri_nodeize(real_fmri);
nvlist_free(resource);
break;
case DT_DEV:
if ((ret = config_bydev_lookup(Lastcfg, path)) == NULL)
out(O_ALTFP, "platform_getpath: no configuration node "
"has device path matching \"%s\".", path);
break;
case DT_TP:
if ((ret = config_bytp_lookup(Lastcfg, tp)) == NULL)
out(O_ALTFP, "platform_getpath: no configuration node "
"has tp matching \"%s\".", tp);
break;
case DT_DEVID:
if ((ret = config_bydevid_lookup(Lastcfg, devid)) == NULL)
out(O_ALTFP, "platform_getpath: no configuration node "
"has devid matching \"%s\".", devid);
break;
case DT_CPU:
if ((ret = config_bycpuid_lookup(Lastcfg, cpuid)) == NULL)
out(O_ALTFP, "platform_getpath: no configuration node "
"has cpu-id matching %u.", cpuid);
break;
}
structconfig_free(Lastcfg->cooked);
config_free(Lastcfg);
in_getpath = 0;
return (ret);
}
#define STRSBUFLEN 512
static void
cfgadjust(struct cfgdata *rawdata, int addlen)
{
int curnext, newlen;
if (rawdata->nextfree + addlen >= rawdata->end) {
newlen = (((rawdata->nextfree - rawdata->begin + 1 + addlen)
/ STRSBUFLEN) + 1) * STRSBUFLEN;
curnext = rawdata->nextfree - rawdata->begin;
rawdata->begin = REALLOC(rawdata->begin, newlen);
rawdata->nextfree = rawdata->begin + curnext;
rawdata->end = rawdata->begin + newlen;
}
}
static char *
hc_path(tnode_t *node)
{
int i, err;
char *name, *instance, *estr;
nvlist_t *fmri, **hcl;
ulong_t ul;
uint_t nhc;
if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
&fmri, &err) < 0)
return (NULL);
if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &nhc)
!= 0) {
nvlist_free(fmri);
return (NULL);
}
tmpbuf[0] = '\0';
for (i = 0; i < nhc; ++i) {
err = nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
err |= nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &instance);
if (err) {
nvlist_free(fmri);
return (NULL);
}
ul = strtoul(instance, &estr, 10);
if (estr == instance) {
nvlist_free(fmri);
return (NULL);
}
(void) strlcat(tmpbuf, "/", MAXPATHLEN);
(void) strlcat(tmpbuf, name, MAXPATHLEN);
(void) snprintf(numbuf, MAXPATHLEN, "%lu", ul);
(void) strlcat(tmpbuf, numbuf, MAXPATHLEN);
lastcomp = stable(name);
}
nvlist_free(fmri);
return (tmpbuf);
}
static void
add_prop_val(topo_hdl_t *thp, struct cfgdata *rawdata, char *propn,
nvpair_t *pv_nvp)
{
int addlen, err;
char *propv, *fmristr = NULL;
nvlist_t *fmri;
uint32_t ui32;
int64_t i64;
int32_t i32;
boolean_t bool;
uint64_t ui64;
char buf[32];
uint_t nelem;
int i, j, sz;
char **propvv;
if (propn == NULL)
return;
switch (nvpair_type(pv_nvp)) {
case DATA_TYPE_STRING_ARRAY:
(void) nvpair_value_string_array(pv_nvp, &propvv, &nelem);
for (sz = 0, i = 0; i < nelem; i++)
sz += strlen(propvv[i]) + 1;
propv = MALLOC(sz);
for (j = 0, i = 0; i < nelem; j++, i++) {
(void) strcpy(&propv[j], propvv[i]);
j += strlen(propvv[i]);
if (i < nelem - 1)
propv[j] = ' ';
}
break;
case DATA_TYPE_STRING:
(void) nvpair_value_string(pv_nvp, &propv);
break;
case DATA_TYPE_NVLIST:
(void) nvpair_value_nvlist(pv_nvp, &fmri);
if (topo_fmri_nvl2str(thp, fmri, &fmristr, &err) < 0) {
out(O_ALTFP, "cfgcollect: failed to convert fmri to "
"string");
return;
} else {
propv = fmristr;
}
break;
case DATA_TYPE_UINT64:
(void) nvpair_value_uint64(pv_nvp, &ui64);
(void) snprintf(buf, sizeof (buf), "0x%llx", ui64);
propv = buf;
break;
case DATA_TYPE_BOOLEAN_VALUE:
(void) nvpair_value_boolean_value(pv_nvp, &bool);
(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)bool);
propv = buf;
break;
case DATA_TYPE_INT32:
(void) nvpair_value_int32(pv_nvp, &i32);
(void) snprintf(buf, sizeof (buf), "0x%llx",
(uint64_t)(int64_t)i32);
propv = buf;
break;
case DATA_TYPE_INT64:
(void) nvpair_value_int64(pv_nvp, &i64);
(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)i64);
propv = buf;
break;
case DATA_TYPE_UINT32:
(void) nvpair_value_uint32(pv_nvp, &ui32);
(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)ui32);
propv = buf;
break;
default:
out(O_ALTFP, "cfgcollect: failed to get property value for "
"%s", propn);
return;
}
addlen = strlen(propn) + strlen(propv) + 2;
cfgadjust(rawdata, addlen);
(void) snprintf(rawdata->nextfree,
rawdata->end - rawdata->nextfree, "%s=%s",
propn, propv);
if (strcmp(propn, TOPO_PROP_RESOURCE) == 0)
out(O_ALTFP|O_VERB3, "cfgcollect: %s", propv);
if (nvpair_type(pv_nvp) == DATA_TYPE_STRING_ARRAY)
FREE(propv);
rawdata->nextfree += addlen;
if (fmristr != NULL)
topo_hdl_strfree(thp, fmristr);
}
static int
cfgcollect(topo_hdl_t *thp, tnode_t *node, void *arg)
{
struct cfgdata *rawdata = (struct cfgdata *)arg;
int err, addlen;
char *propn, *path = NULL;
nvlist_t *p_nv, *pg_nv, *pv_nv;
nvpair_t *nvp, *pg_nvp, *pv_nvp;
if (topo_node_flags(node) == TOPO_NODE_FACILITY)
return (TOPO_WALK_NEXT);
path = hc_path(node);
if (path == NULL)
return (TOPO_WALK_ERR);
addlen = strlen(path) + 1;
cfgadjust(rawdata, addlen);
(void) strcpy(rawdata->nextfree, path);
rawdata->nextfree += addlen;
if (!in_getpath && prune_raw_config &&
lut_lookup(Usednames, (void *)lastcomp, NULL) == NULL)
return (TOPO_WALK_NEXT);
p_nv = topo_prop_getprops(node, &err);
for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
nvp = nvlist_next_nvpair(p_nv, nvp)) {
if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
nvpair_type(nvp) != DATA_TYPE_NVLIST)
continue;
(void) nvpair_value_nvlist(nvp, &pg_nv);
for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) != 0 ||
nvpair_type(pg_nvp) != DATA_TYPE_NVLIST)
continue;
(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
propn = NULL;
for (pv_nvp = nvlist_next_nvpair(pv_nv, NULL);
pv_nvp != NULL;
pv_nvp = nvlist_next_nvpair(pv_nv, pv_nvp)) {
if (strcmp(TOPO_PROP_VAL_NAME,
nvpair_name(pv_nvp)) == 0)
(void) nvpair_value_string(pv_nvp,
&propn);
if (strcmp(TOPO_PROP_VAL_VAL,
nvpair_name(pv_nvp)) == 0)
add_prop_val(thp, rawdata, propn,
pv_nvp);
}
}
}
nvlist_free(p_nv);
return (TOPO_WALK_NEXT);
}
void
platform_restore_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
{
if (hdl == Lasthdl && fmcase == Lastfmcase) {
size_t cfglen;
fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFGLEN, (void *)&cfglen,
sizeof (size_t));
Lastcfg->begin = MALLOC(cfglen);
Lastcfg->end = Lastcfg->nextfree = Lastcfg->begin + cfglen;
fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFG, Lastcfg->begin,
cfglen);
Lasthdl = NULL;
Lastfmcase = NULL;
}
}
void
platform_save_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
{
size_t cfglen;
Lastfmcase = fmcase;
Lasthdl = hdl;
cfglen = Lastcfg->nextfree - Lastcfg->begin;
fmd_buf_create(hdl, fmcase, WOBUF_CFGLEN, sizeof (cfglen));
fmd_buf_write(hdl, fmcase, WOBUF_CFGLEN, (void *)&cfglen,
sizeof (cfglen));
if (cfglen != 0) {
fmd_buf_create(hdl, fmcase, WOBUF_CFG, cfglen);
fmd_buf_write(hdl, fmcase, WOBUF_CFG, Lastcfg->begin, cfglen);
}
FREE(Lastcfg->begin);
Lastcfg->begin = NULL;
Lastcfg->end = NULL;
Lastcfg->nextfree = NULL;
}
struct cfgdata *
platform_config_snapshot(void)
{
int err;
topo_walk_t *twp;
static uint64_t lastgen;
uint64_t curgen;
if (prune_raw_config == 0 && (curgen = fmd_fmri_get_drgen()) <=
lastgen && Lastcfg != NULL) {
Lastcfg->raw_refcnt++;
if (Lastcfg->begin == NULL)
platform_restore_config(Lasthdl, Lastfmcase);
return (Lastcfg);
}
lastgen = curgen;
if (Lastcfg != NULL) {
config_free(Lastcfg);
}
Lastcfg = MALLOC(sizeof (struct cfgdata));
Lastcfg->raw_refcnt = 2;
Lastcfg->begin = Lastcfg->nextfree = Lastcfg->end = NULL;
Lastcfg->cooked = NULL;
Lastcfg->devcache = NULL;
Lastcfg->devidcache = NULL;
Lastcfg->tpcache = NULL;
Lastcfg->cpucache = NULL;
fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
if ((twp = topo_walk_init(Eft_topo_hdl, FM_FMRI_SCHEME_HC, cfgcollect,
Lastcfg, &err)) == NULL) {
out(O_DIE, "platform_config_snapshot: NULL topology tree: %s",
topo_strerror(err));
}
if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
topo_walk_fini(twp);
out(O_DIE, "platform_config_snapshot: error walking topology "
"tree");
}
topo_walk_fini(twp);
out(O_ALTFP|O_STAMP, "raw config complete");
return (Lastcfg);
}
static const char *
cfgstrprop_lookup(struct config *croot, char *path, const char *pname)
{
struct config *cresource;
const char *fmristr;
if ((cresource = config_lookup(croot, path, 0)) == NULL) {
out(O_ALTFP, "Cannot find config info for %s.", path);
return (NULL);
}
if ((fmristr = config_getprop(cresource, pname)) == NULL) {
out(O_ALTFP, "Cannot find %s property for %s resource "
"re-write", pname, path);
return (NULL);
}
return (fmristr);
}
void
platform_unit_translate(int isdefect, struct config *croot, const char *prop,
nvlist_t **fmrip, char *path)
{
const char *fmristr;
char *serial;
nvlist_t *fmri;
int err;
fmristr = cfgstrprop_lookup(croot, path, prop);
if (fmristr == NULL) {
out(O_ALTFP, "Cannot rewrite unit FMRI for %s.", path);
return;
}
if (topo_fmri_str2nvl(Eft_topo_hdl, fmristr, &fmri, &err) < 0) {
out(O_ALTFP, "Can not convert config info: %s",
topo_strerror(err));
out(O_ALTFP, "Cannot rewrite unit FMRI for %s.", path);
return;
}
if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &serial) != 0) {
serial = (char *)cfgstrprop_lookup(croot, path,
FM_FMRI_HC_SERIAL_ID);
if (serial != NULL)
(void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
serial);
}
*fmrip = fmri;
}
static char **
platform_get_files(const char *dirname[], const char *fnstr, int nodups)
{
DIR *dirp;
struct dirent *dp;
struct lut *foundnames = NULL;
char **files = NULL;
int nfiles = 0;
int slots = 0;
size_t fnlen, d_namelen;
size_t totlen;
int i;
static char *nullav;
ASSERT(fnstr != NULL);
fnlen = strlen(fnstr);
for (i = 0; dirname[i] != NULL; i++) {
out(O_VERB, "Looking for %s files in %s", fnstr, dirname[i]);
if ((dirp = opendir(dirname[i])) == NULL) {
out(O_DEBUG|O_SYS,
"platform_get_files: opendir failed for %s",
dirname[i]);
continue;
}
while ((dp = readdir(dirp)) != NULL) {
if ((fnlen == 1 && *fnstr == '*') ||
((d_namelen = strlen(dp->d_name)) >= fnlen &&
strncmp(dp->d_name + d_namelen - fnlen,
fnstr, fnlen) == 0)) {
if (nodups != 0) {
const char *snm = stable(dp->d_name);
if (lut_lookup(foundnames,
(void *)snm,
NULL) != NULL) {
out(O_VERB,
"platform_get_files: "
"skipping repeated name "
"%s/%s",
dirname[i],
snm);
continue;
}
foundnames = lut_add(foundnames,
(void *)snm,
(void *)snm,
NULL);
}
if (nfiles > slots - 2) {
slots += 10;
files = (char **)REALLOC(files,
slots * sizeof (char *));
}
totlen = strlen(dirname[i]) + 1;
totlen += strlen(dp->d_name) + 1;
files[nfiles] = MALLOC(totlen);
out(O_VERB, "File %d: \"%s/%s\"", nfiles,
dirname[i], dp->d_name);
(void) snprintf(files[nfiles++], totlen,
"%s/%s", dirname[i], dp->d_name);
}
}
(void) closedir(dirp);
}
if (foundnames != NULL)
lut_free(foundnames, NULL, NULL);
if (nfiles == 0)
return (&nullav);
files[nfiles] = NULL;
return (files);
}
static char **
platform_get_files_stddirs(char *fname, int nodups)
{
const char *dirlist[4];
char **flist;
char *eftgendir, *eftmachdir, *eftplatdir;
eftgendir = MALLOC(MAXPATHLEN);
eftmachdir = MALLOC(MAXPATHLEN);
eftplatdir = MALLOC(MAXPATHLEN);
(void) snprintf(eftgendir, MAXPATHLEN, "%s/usr/lib/fm/eft", Root);
(void) snprintf(eftmachdir,
MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Mach);
(void) snprintf(eftplatdir,
MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Plat);
dirlist[0] = eftplatdir;
dirlist[1] = eftmachdir;
dirlist[2] = eftgendir;
dirlist[3] = NULL;
flist = platform_get_files(dirlist, fname, nodups);
FREE(eftplatdir);
FREE(eftmachdir);
FREE(eftgendir);
return (flist);
}
void
platform_run_poller(const char *poller)
{
}
static int
forkandexecve(const char *path, char *const argv[], char *const envp[],
char *outbuf, size_t outbuflen, char *errbuf, size_t errbuflen)
{
pid_t pid;
int outpipe[2], errpipe[2];
int rt = 0;
if (pipe(outpipe) < 0)
if (strlcat(errbuf, ": pipe(outpipe) failed",
errbuflen) >= errbuflen)
return (1);
if (pipe(errpipe) < 0)
if (strlcat(errbuf, ": pipe(errpipe) failed",
errbuflen) >= errbuflen)
return (1);
if ((pid = fork()) < 0) {
rt = (int)strlcat(errbuf, ": fork() failed", errbuflen);
} else if (pid) {
int wstat, count;
(void) close(errpipe[1]);
(void) close(outpipe[1]);
if (waitpid(pid, &wstat, 0) < 0)
if (strlcat(errbuf, ": waitpid() failed",
errbuflen) >= errbuflen)
return (1);
if (ioctl(errpipe[0], FIONREAD, &count) >= 0 && count) {
if (read(errpipe[0], errbuf, errbuflen) <= 0) {
if (strlcat(errbuf, ": read(errpipe) failed",
errbuflen) >= errbuflen)
return (1);
}
if (count > errbuflen - 1)
count = errbuflen - 1;
if (errbuf[count - 1] != '\0' &&
errbuf[count - 1] != '\n')
errbuf[count] = '\0';
} else if (WIFSIGNALED(wstat))
if (strlcat(errbuf, ": signaled",
errbuflen) >= errbuflen)
return (1);
else if (WIFEXITED(wstat) && WEXITSTATUS(wstat))
if (strlcat(errbuf, ": abnormal exit",
errbuflen) >= errbuflen)
return (1);
if (ioctl(outpipe[0], FIONREAD, &count) >= 0 && count) {
if (read(outpipe[0], outbuf, outbuflen) <= 0) {
if (strlcat(errbuf, ": read(outpipe) failed",
errbuflen) >= errbuflen)
return (1);
}
if (count > outbuflen - 1)
count = outbuflen - 1;
if (outbuf[count - 1] != '\0' &&
outbuf[count - 1] != '\n')
outbuf[count] = '\0';
}
(void) close(errpipe[0]);
(void) close(outpipe[0]);
} else {
(void) dup2(errpipe[1], fileno(stderr));
(void) close(errpipe[0]);
(void) dup2(outpipe[1], fileno(stdout));
(void) close(outpipe[0]);
if (execve(path, argv, envp))
perror(path);
_exit(1);
}
return (rt);
}
#define MAXDIGITIDX 23
static int
arglist2argv(struct node *np, struct lut **globals, struct config *croot,
struct arrow *arrowp, char ***argv, int *argc, int *argvlen)
{
struct node *namep;
char numbuf[MAXDIGITIDX + 1];
char *numstr, *nullbyte;
char *addthisarg = NULL;
if (np == NULL)
return (0);
switch (np->t) {
case T_QUOTE:
addthisarg = STRDUP(np->u.func.s);
break;
case T_LIST:
if (arglist2argv(np->u.expr.left, globals, croot, arrowp,
argv, argc, argvlen))
return (1);
ASSERT(*argc > 0);
if (arglist2argv(np->u.expr.right, globals, croot, arrowp,
argv, argc, argvlen))
return (1);
break;
case T_FUNC:
case T_GLOBID:
case T_ASSIGN:
case T_CONDIF:
case T_CONDELSE:
case T_EQ:
case T_NE:
case T_LT:
case T_LE:
case T_GT:
case T_GE:
case T_BITAND:
case T_BITOR:
case T_BITXOR:
case T_BITNOT:
case T_LSHIFT:
case T_RSHIFT:
case T_AND:
case T_OR:
case T_NOT:
case T_ADD:
case T_SUB:
case T_MUL:
case T_DIV:
case T_MOD: {
struct evalue value;
if (!eval_expr(np, NULL, NULL, globals, croot, arrowp,
0, &value))
return (1);
switch (value.t) {
case UINT64:
numbuf[MAXDIGITIDX] = '\0';
nullbyte = &numbuf[MAXDIGITIDX];
numstr = ulltostr(value.v, nullbyte);
addthisarg = STRDUP(numstr);
break;
case STRING:
addthisarg = STRDUP((const char *)(uintptr_t)value.v);
break;
case NODEPTR :
namep = (struct node *)(uintptr_t)value.v;
addthisarg = ipath2str(NULL, ipath(namep));
break;
default:
out(O_ERR,
"call: arglist2argv: unexpected result from"
" operation %s",
ptree_nodetype2str(np->t));
return (1);
}
break;
}
case T_NUM:
case T_TIMEVAL:
numbuf[MAXDIGITIDX] = '\0';
nullbyte = &numbuf[MAXDIGITIDX];
numstr = ulltostr(np->u.ull, nullbyte);
addthisarg = STRDUP(numstr);
break;
case T_NAME:
addthisarg = ipath2str(NULL, ipath(np));
break;
case T_EVENT:
addthisarg = ipath2str(np->u.event.ename->u.name.s,
ipath(np->u.event.epname));
break;
default:
out(O_ERR, "call: arglist2argv: node type %s is unsupported",
ptree_nodetype2str(np->t));
return (1);
break;
}
if (*argc == 0 && addthisarg != NULL) {
char **files;
files = platform_get_files_stddirs(addthisarg, 0);
if (files[0] == NULL)
out(O_DIE, "call: function %s not found", addthisarg);
if (files[1] != NULL)
out(O_DIE, "call: multiple functions %s found",
addthisarg);
FREE(addthisarg);
addthisarg = STRDUP(files[0]);
FREE(files[0]);
FREE(files);
}
if (addthisarg != NULL) {
if (*argc >= *argvlen - 2) {
*argvlen += 10;
*argv = (char **)REALLOC(*argv,
sizeof (char *) * *argvlen);
}
(*argv)[*argc] = addthisarg;
(*argc)++;
(*argv)[*argc] = NULL;
}
return (0);
}
static int
generate_envp(struct arrow *arrowp, char ***envp, int *envc, int *envplen)
{
char *envnames[] = { "EFT_FROM_EVENT", "EFT_TO_EVENT",
"EFT_FILE", "EFT_LINE", NULL };
char *envvalues[4];
char *none = "(none)";
size_t elen;
int i;
*envc = 4;
*envplen = *envc + 1;
*envp = (char **)MALLOC(sizeof (char *) * *envplen);
envvalues[0] = ipath2str(
arrowp->tail->myevent->enode->u.event.ename->u.name.s,
arrowp->tail->myevent->ipp);
envvalues[1] = ipath2str(
arrowp->head->myevent->enode->u.event.ename->u.name.s,
arrowp->head->myevent->ipp);
if (arrowp->head->myevent->enode->file == NULL) {
envvalues[2] = STRDUP(none);
envvalues[3] = STRDUP(none);
} else {
envvalues[2] = STRDUP(arrowp->head->myevent->enode->file);
envvalues[3] = MALLOC(sizeof (char) * 25);
(void) snprintf(envvalues[3], sizeof (envvalues[3]), "%d",
arrowp->head->myevent->enode->line);
}
for (i = 0; envnames[i] != NULL && i < *envc; i++) {
elen = strlen(envnames[i]) + strlen(envvalues[i]) + 2;
(*envp)[i] = MALLOC(elen);
(void) snprintf((*envp)[i], elen, "%s=%s",
envnames[i], envvalues[i]);
FREE(envvalues[i]);
}
(*envp)[*envc] = NULL;
return (0);
}
int
platform_call(struct node *np, struct lut **globals, struct config *croot,
struct arrow *arrowp, struct evalue *valuep)
{
char outbuf[256], errbuf[512];
struct stat buf;
char **argv, **envp;
int argc, argvlen, envc, envplen;
int i, ret;
ASSERT(np->t == T_LIST);
argv = NULL;
argc = 0;
argvlen = 0;
if (arglist2argv(np, globals, croot, arrowp, &argv, &argc, &argvlen) ||
argc == 0)
return (1);
if (stat(argv[0], &buf) == 0) {
int exec_bit_set = 0;
if (buf.st_uid == geteuid() && buf.st_mode & S_IXUSR)
exec_bit_set = 1;
else if (buf.st_gid == getegid() && buf.st_mode & S_IXGRP)
exec_bit_set = 1;
else if (buf.st_mode & S_IXOTH)
exec_bit_set = 1;
if (exec_bit_set == 0)
out(O_DIE, "call: executable bit not set on %s",
argv[0]);
} else {
out(O_DIE, "call: failure in stat(), errno = %d\n", errno);
}
envp = NULL;
envc = 0;
envplen = 0;
if (generate_envp(arrowp, &envp, &envc, &envplen))
return (1);
outbuf[0] = '\0';
errbuf[0] = '\0';
ret = forkandexecve((const char *) argv[0], (char *const *) argv,
(char *const *) envp, outbuf, sizeof (outbuf),
errbuf, sizeof (errbuf));
for (i = 0; i < envc; i++)
FREE(envp[i]);
if (envp)
FREE(envp);
if (ret) {
outfl(O_OK, np->file, np->line,
"call: failure in fork + exec of %s", argv[0]);
} else {
char *ptr;
for (ptr = outbuf; *ptr; ptr++)
if (*ptr == '\n' || *ptr == '\r') {
*ptr = '\0';
break;
}
valuep->t = STRING;
valuep->v = (uintptr_t)stable(outbuf);
}
if (errbuf[0] != '\0') {
ret = 1;
outfl(O_OK, np->file, np->line,
"call: unexpected stderr output from %s: %s",
argv[0], errbuf);
}
for (i = 0; i < argc; i++)
FREE(argv[i]);
FREE(argv);
return (ret);
}
int
platform_confcall(struct node *np, struct lut **globals, struct config *croot,
struct arrow *arrowp, struct evalue *valuep)
{
outfl(O_ALTFP|O_VERB, np->file, np->line, "unknown confcall");
return (0);
}
char **
platform_get_eft_files(void)
{
return (platform_get_files_stddirs(".eft", 1));
}
void
platform_free_eft_files(char **flist)
{
char **f;
if (flist == NULL || *flist == NULL)
return;
f = flist;
while (*f != NULL) {
FREE(*f);
f++;
}
FREE(flist);
}
static nvlist_t *payloadnvp = NULL;
void
platform_set_payloadnvp(nvlist_t *nvlp)
{
ASSERT(payloadnvp != NULL ? nvlp == NULL : 1);
payloadnvp = nvlp;
}
static int
get_array_info(const char *inputstr, const char **name, unsigned int *index)
{
char *indexptr, *indexend, *dupname, *endname;
if (strchr(inputstr, '[') == NULL)
return (1);
dupname = STRDUP(inputstr);
indexptr = strchr(dupname, '[');
indexend = strchr(dupname, ']');
if (indexend == NULL || indexptr >= indexend ||
strchr(indexptr, '-') != NULL) {
FREE(dupname);
return (1);
}
endname = indexptr;
while (isspace(*(endname - 1)) && dupname < endname)
endname--;
*endname = '\0';
ASSERT(dupname < endname);
while (!isdigit(*indexptr) && indexptr < indexend)
indexptr++;
while (!isdigit(*indexend) && indexptr <= indexend)
indexend--;
*(indexend + 1) = '\0';
*index = (unsigned int)atoi(indexptr);
*name = stable(dupname);
FREE(dupname);
return (0);
}
int
platform_payloadprop(struct node *np, struct evalue *valuep)
{
nvlist_t *basenvp;
nvlist_t *embnvp = NULL;
nvpair_t *nvpair;
const char *nameptr, *propstr, *lastnameptr;
int not_array = 0;
unsigned int index = 0;
uint_t nelem;
char *nvpname, *nameslist = NULL;
char *scheme = NULL;
ASSERT(np->t == T_QUOTE);
propstr = np->u.quote.s;
if (payloadnvp == NULL) {
out(O_ALTFP | O_VERB2, "platform_payloadprop: no nvp for %s",
propstr);
return (1);
}
basenvp = payloadnvp;
if (strchr(propstr, '.') != NULL) {
nvlist_t **arraynvp;
uint_t nelem;
char *w;
int ier;
nameslist = STRDUP(propstr);
lastnameptr = strtok(nameslist, ".");
while ((w = strtok(NULL, ".")) != NULL) {
if (get_array_info(lastnameptr, &nameptr, &index)) {
ier = nvlist_lookup_nvlist(basenvp,
lastnameptr, &basenvp);
} else {
ier = nvlist_lookup_nvlist_array(basenvp,
nameptr, &arraynvp, &nelem);
if (ier == 0) {
if ((uint_t)index > nelem - 1)
ier = 1;
else
basenvp = arraynvp[index];
}
}
if (ier) {
out(O_ALTFP, "platform_payloadprop: "
" invalid list for %s (in %s)",
lastnameptr, propstr);
FREE(nameslist);
return (1);
}
lastnameptr = w;
}
} else {
lastnameptr = propstr;
}
not_array = get_array_info(lastnameptr, &nameptr, &index);
if (not_array)
nameptr = stable(lastnameptr);
if (nameslist != NULL)
FREE(nameslist);
nvpair = NULL;
while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
nvpname = nvpair_name(nvpair);
ASSERT(nvpname != NULL);
if (nameptr == stable(nvpname))
break;
}
if (nvpair == NULL) {
out(O_ALTFP, "platform_payloadprop: no entry for %s", propstr);
return (1);
} else if (valuep == NULL) {
return (0);
}
valuep->t = UNDEFINED;
(void) nvpair_value_nvlist(nvpair, &embnvp);
if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME, &scheme) == 0) {
if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
valuep->t = NODEPTR;
valuep->v = (uintptr_t)hc_fmri_nodeize(embnvp);
return (0);
}
}
switch (nvpair_type(nvpair)) {
case DATA_TYPE_BOOLEAN:
case DATA_TYPE_BOOLEAN_VALUE: {
boolean_t val;
(void) nvpair_value_boolean_value(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_BYTE: {
uchar_t val;
(void) nvpair_value_byte(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_STRING: {
char *val;
valuep->t = STRING;
(void) nvpair_value_string(nvpair, &val);
valuep->v = (uintptr_t)stable(val);
break;
}
case DATA_TYPE_INT8: {
int8_t val;
(void) nvpair_value_int8(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_UINT8: {
uint8_t val;
(void) nvpair_value_uint8(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_INT16: {
int16_t val;
(void) nvpair_value_int16(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_UINT16: {
uint16_t val;
(void) nvpair_value_uint16(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_INT32: {
int32_t val;
(void) nvpair_value_int32(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_UINT32: {
uint32_t val;
(void) nvpair_value_uint32(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_INT64: {
int64_t val;
(void) nvpair_value_int64(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_UINT64: {
uint64_t val;
(void) nvpair_value_uint64(nvpair, &val);
valuep->t = UINT64;
valuep->v = (unsigned long long)val;
break;
}
case DATA_TYPE_BOOLEAN_ARRAY: {
boolean_t *val;
(void) nvpair_value_boolean_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_BYTE_ARRAY: {
uchar_t *val;
(void) nvpair_value_byte_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_STRING_ARRAY: {
char **val;
(void) nvpair_value_string_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = STRING;
valuep->v = (uintptr_t)stable(val[index]);
break;
}
case DATA_TYPE_INT8_ARRAY: {
int8_t *val;
(void) nvpair_value_int8_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_UINT8_ARRAY: {
uint8_t *val;
(void) nvpair_value_uint8_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_INT16_ARRAY: {
int16_t *val;
(void) nvpair_value_int16_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_UINT16_ARRAY: {
uint16_t *val;
(void) nvpair_value_uint16_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_INT32_ARRAY: {
int32_t *val;
(void) nvpair_value_int32_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_UINT32_ARRAY: {
uint32_t *val;
(void) nvpair_value_uint32_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_INT64_ARRAY: {
int64_t *val;
(void) nvpair_value_int64_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
case DATA_TYPE_UINT64_ARRAY: {
uint64_t *val;
(void) nvpair_value_uint64_array(nvpair, &val, &nelem);
if (not_array == 1 || index >= nelem)
goto invalid;
valuep->t = UINT64;
valuep->v = (unsigned long long)val[index];
break;
}
default :
out(O_ALTFP|O_VERB2,
"platform_payloadprop: unsupported data type for %s",
propstr);
return (1);
}
return (0);
invalid:
out(O_ALTFP|O_VERB2,
"platform_payloadprop: invalid array reference for %s", propstr);
return (1);
}
int
platform_path_exists(nvlist_t *fmri)
{
return (fmd_nvl_fmri_present(Hdl, fmri));
}
struct evalue *
platform_payloadprop_values(const char *propstr, int *nvals)
{
struct evalue *retvals;
nvlist_t *basenvp;
nvpair_t *nvpair;
char *nvpname;
*nvals = 0;
if (payloadnvp == NULL)
return (NULL);
basenvp = payloadnvp;
nvpair = NULL;
while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
nvpname = nvpair_name(nvpair);
ASSERT(nvpname != NULL);
if (strcmp(propstr, nvpname) == 0)
break;
}
if (nvpair == NULL)
return (NULL);
switch (nvpair_type(nvpair)) {
case DATA_TYPE_NVLIST: {
nvlist_t *embnvp = NULL;
char *scheme = NULL;
(void) nvpair_value_nvlist(nvpair, &embnvp);
if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME,
&scheme) == 0) {
if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
retvals->t = NODEPTR;
retvals->v =
(uintptr_t)hc_fmri_nodeize(embnvp);
return (retvals);
}
}
return (NULL);
}
case DATA_TYPE_NVLIST_ARRAY: {
char *scheme = NULL;
nvlist_t **nvap;
uint_t nel;
int i;
int hccount;
if (nvpair_value_nvlist_array(nvpair, &nvap, &nel) != 0)
return (NULL);
hccount = 0;
for (i = 0; i < nel; i++) {
if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
&scheme) == 0 &&
strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
hccount++;
}
}
if (hccount == 0)
return (NULL);
*nvals = hccount;
retvals = MALLOC(sizeof (struct evalue) * hccount);
hccount = 0;
for (i = 0; i < nel; i++) {
if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
&scheme) == 0 &&
strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
retvals[hccount].t = NODEPTR;
retvals[hccount].v = (uintptr_t)
hc_fmri_nodeize(nvap[i]);
hccount++;
}
}
return (retvals);
}
case DATA_TYPE_BOOLEAN:
case DATA_TYPE_BOOLEAN_VALUE: {
boolean_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_boolean_value(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_BYTE: {
uchar_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_byte(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_STRING: {
char *val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
retvals->t = STRING;
(void) nvpair_value_string(nvpair, &val);
retvals->v = (uintptr_t)stable(val);
return (retvals);
}
case DATA_TYPE_INT8: {
int8_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_int8(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_UINT8: {
uint8_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_uint8(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_INT16: {
int16_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_int16(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_UINT16: {
uint16_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_uint16(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_INT32: {
int32_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_int32(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_UINT32: {
uint32_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_uint32(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_INT64: {
int64_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_int64(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_UINT64: {
uint64_t val;
*nvals = 1;
retvals = MALLOC(sizeof (struct evalue));
(void) nvpair_value_uint64(nvpair, &val);
retvals->t = UINT64;
retvals->v = (unsigned long long)val;
return (retvals);
}
case DATA_TYPE_BOOLEAN_ARRAY: {
boolean_t *val;
uint_t nel;
int i;
(void) nvpair_value_boolean_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_BYTE_ARRAY: {
uchar_t *val;
uint_t nel;
int i;
(void) nvpair_value_byte_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_STRING_ARRAY: {
char **val;
uint_t nel;
int i;
(void) nvpair_value_string_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = STRING;
retvals[i].v = (uintptr_t)stable(val[i]);
}
return (retvals);
}
case DATA_TYPE_INT8_ARRAY: {
int8_t *val;
uint_t nel;
int i;
(void) nvpair_value_int8_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_UINT8_ARRAY: {
uint8_t *val;
uint_t nel;
int i;
(void) nvpair_value_uint8_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_INT16_ARRAY: {
int16_t *val;
uint_t nel;
int i;
(void) nvpair_value_int16_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_UINT16_ARRAY: {
uint16_t *val;
uint_t nel;
int i;
(void) nvpair_value_uint16_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_INT32_ARRAY: {
int32_t *val;
uint_t nel;
int i;
(void) nvpair_value_int32_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_UINT32_ARRAY: {
uint32_t *val;
uint_t nel;
int i;
(void) nvpair_value_uint32_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_INT64_ARRAY: {
int64_t *val;
uint_t nel;
int i;
(void) nvpair_value_int64_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
case DATA_TYPE_UINT64_ARRAY: {
uint64_t *val;
uint_t nel;
int i;
(void) nvpair_value_uint64_array(nvpair, &val, &nel);
*nvals = nel;
retvals = MALLOC(sizeof (struct evalue) * nel);
for (i = 0; i < nel; i++) {
retvals[i].t = UINT64;
retvals[i].v = (unsigned long long)val[i];
}
return (retvals);
}
}
return (NULL);
}
const struct ipath *
platform_fault2ipath(nvlist_t *flt)
{
nvlist_t *rsrc;
struct node *np;
char *scheme;
const struct ipath *ip;
if (nvlist_lookup_nvlist(flt, FM_FAULT_RESOURCE, &rsrc) != 0) {
out(O_ALTFP, "platform_fault2ipath: no resource member");
return (NULL);
} else if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0) {
out(O_ALTFP, "platform_fault2ipath: no scheme type for rsrc");
return (NULL);
}
if (strncmp(scheme, FM_FMRI_SCHEME_HC,
sizeof (FM_FMRI_SCHEME_HC) - 1) != 0) {
out(O_ALTFP, "platform_fault2ipath: returning NULL for non-hc "
"scheme %s", scheme);
return (NULL);
}
if ((np = hc_fmri_nodeize(rsrc)) == NULL)
return (NULL);
ip = ipath(np);
tree_free(np);
return (ip);
}