#include <sys/types.h>
#include <sys/param.h>
#include <sys/mdesc.h>
#include <sys/mdesc_impl.h>
md_t *
md_init_intern(uint64_t *ptr, void *(*allocp)(size_t),
void (*freep)(void *, size_t))
{
md_impl_t *mdp;
int idx;
int count;
int done;
uint64_t gen;
mde_str_cookie_t root_name;
if ((((uintptr_t)ptr) & 7) != 0)
return (NULL);
mdp = (md_impl_t *)allocp(sizeof (md_impl_t));
if (mdp == NULL)
return (NULL);
mdp->allocp = allocp;
mdp->freep = freep;
mdp->caddr = (char *)ptr;
mdp->headerp = (md_header_t *)mdp->caddr;
if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) {
goto cleanup_nohash;
}
mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz);
mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz);
mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz);
mdp->size = MD_HEADER_SIZE + mdp->node_blk_size +
mdp->name_blk_size + mdp->data_blk_size;
mdp->mdep = (md_element_t *)(mdp->caddr + MD_HEADER_SIZE);
mdp->namep = (char *)(mdp->caddr + MD_HEADER_SIZE + mdp->node_blk_size);
mdp->datap = (uint8_t *)(mdp->caddr + MD_HEADER_SIZE +
mdp->name_blk_size + mdp->node_blk_size);
mdp->root_node = MDE_INVAL_ELEM_COOKIE;
root_name = md_find_name((md_t *)mdp, "root");
if (root_name == MDE_INVAL_STR_COOKIE) {
goto cleanup;
}
for (done = 0, idx = 0, count = 0; !done; ) {
md_element_t *np;
np = &(mdp->mdep[idx]);
switch (MDE_TAG(np)) {
case MDET_LIST_END:
done = 1;
break;
case MDET_NODE:
if (root_name == MDE_NAME(np)) {
if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) {
goto cleanup;
}
mdp->root_node = (mde_cookie_t)idx;
}
idx = MDE_PROP_INDEX(np);
count++;
break;
default:
idx++;
}
}
if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) {
goto cleanup;
}
mdp->element_count = idx + 1;
mdp->node_count = count;
if (mdp->element_count != (mdp->node_blk_size / MD_ELEMENT_SIZE))
goto cleanup;
mdp->md_magic = LIBMD_MAGIC;
if (md_get_prop_val((md_t *)mdp, mdp->root_node,
"md-generation#", &gen) != 0)
mdp->gen = MDESC_INVAL_GEN;
else
mdp->gen = gen;
return ((md_t *)mdp);
cleanup:
cleanup_nohash:
mdp->freep(mdp, sizeof (md_impl_t));
return (NULL);
}