ERL_NIF_TERM
vert_virSecretGetValue(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *sp = NULL;
    u_int32_t flags = 0;
    size_t value_size = 0;

    unsigned char *secret = NULL;
    ERL_NIF_TERM buf = {0};


    VERT_GET_RESOURCE(0, sp, VERT_RES_SECRET);
    VERT_GET_UINT(1, flags);

    secret = virSecretGetValue(sp->res, &value_size, flags);
    VERTERR(secret == NULL);

    BINCOPY(buf, secret, value_size);

    free(secret);

    return enif_make_tuple2(env,
            atom_ok,
            buf);
}
    ERL_NIF_TERM
vert_virSecretLookupByUsage(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *vp = NULL;
    int usageType = 0;
    ErlNifBinary usageID = {0};

    VERT_RESOURCE *sp = NULL;

    VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT);
    VERT_GET_INT(1, usageType);
    VERT_GET_IOLIST(2, usageID);

    VERT_BIN_APPEND_NULL(usageID);

    VERT_RES_ALLOC(sp, VERT_RES_SECRET, vp->res);

    sp->res = virSecretLookupByUsage(vp->res, usageType, (char *)usageID.data);

    if (sp->res == NULL) {
        enif_release_resource(vp);
        return verterr(env);
    }

    return vert_make_resource(env, sp, atom_secret);
}
    ERL_NIF_TERM
vert_virSecretDefineXML(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *vp = NULL;
    ErlNifBinary xml = {0};
    u_int32_t flags = 0;

    VERT_RESOURCE *sp = NULL;


    VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT);
    VERT_GET_IOLIST(1, xml);
    VERT_GET_UINT(2, flags);

    VERT_BIN_APPEND_NULL(xml);

    VERT_RES_ALLOC(sp, VERT_RES_SECRET, vp->conn);

    sp->res = virSecretDefineXML(vp->res, (char *)xml.data, flags);

    if (sp->res == NULL) {
        enif_release_resource(sp);
        return verterr(env);
    }

    return vert_make_resource(env, sp, atom_secret);
}  
    ERL_NIF_TERM
vert_virNodeNumOfDevices(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *vp = NULL;
    ErlNifBinary cap = {0};
    u_int32_t flags = 0;

    int n = 0;


    VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT);
    VERT_GET_IOLIST(1, cap);
    VERT_GET_UINT(2, flags);

    if (cap.size > 0)
        VERT_BIN_APPEND_NULL(cap);

    n = virNodeNumOfDevices(vp->res,
            (cap.size == 0 ? NULL : (char *)cap.data),
            flags);

    VERTERR(n < 0);

    return enif_make_tuple2(env,
            atom_ok,
            enif_make_int(env, n));
}
    ERL_NIF_TERM
vert_virNodeListDevices(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *vp = NULL;
    ErlNifBinary cap = {0};
    char **names = NULL;
    int maxnames = 0;
    u_int32_t flags = 0;

    int n = 0;
    int rv = 0;
    ERL_NIF_TERM dev = {0};


    VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT);
    VERT_GET_IOLIST(1, cap);
    VERT_GET_INT(2, maxnames);
    VERT_GET_UINT(3, flags);

    if (cap.size > 0)
        VERT_BIN_APPEND_NULL(cap);

    names = calloc(maxnames, sizeof(char *));

    if (names == NULL)
        return error_tuple(env, atom_enomem);

    rv = virNodeListDevices(vp->res,
            (cap.size == 0 ? NULL : (char *)cap.data),
            names, maxnames, flags);

    if (rv < 0)
        goto ERR;

    dev = enif_make_list(env, 0);
    for (n = 0; n < rv; n++) {
        dev = enif_make_list_cell(env,
                enif_make_string(env, names[n], ERL_NIF_LATIN1),
                dev);
    }

    free(names);

    return enif_make_tuple2(env,
            atom_ok,
            dev);

ERR:
    free(names);
    return verterr(env);
}
    ERL_NIF_TERM
vert_virSecretSetValue(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *sp = NULL;
    ErlNifBinary value = {0};
    u_int32_t flags = 0;


    VERT_GET_RESOURCE(0, sp, VERT_RES_SECRET);
    VERT_GET_IOLIST(1, value);
    VERT_GET_UINT(2, flags);

    VERTERR(virSecretSetValue(sp->res, value.data, value.size, flags) < 0);

    return atom_ok;
}
    ERL_NIF_TERM
vert_virStoragePoolGetInfo(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *sp = NULL;
    ErlNifBinary info = {0};


    VERT_GET_RESOURCE(0, sp, VERT_RES_STORAGEPOOL);

    if (!enif_alloc_binary(sizeof(virStoragePoolInfo), &info))
        return error_tuple(env, atom_enomem);

    VERTERR(virStoragePoolGetInfo(sp->res, (virStoragePoolInfoPtr)info.data) < 0);

    return enif_make_tuple2(env,
            atom_ok,
            enif_make_binary(env, &info));
}
    ERL_NIF_TERM
vert_virNodeDeviceListCaps(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *dp = NULL;
    char **names = NULL;
    int maxnames = 0;

    int n = 0;
    int rv = 0;
    ERL_NIF_TERM cap = {0};


    VERT_GET_RESOURCE(0, dp, VERT_RES_NODEDEVICE);
    VERT_GET_INT(1, maxnames);

    names = calloc(maxnames, sizeof(char *));

    if (names == NULL)
        return error_tuple(env, atom_enomem);

    rv = virNodeDeviceListCaps(dp->res, names, maxnames);

    if (rv < 0)
        goto ERR;

    cap = enif_make_list(env, 0);
    for (n = 0; n < rv; n++) {
        cap = enif_make_list_cell(env,
                enif_make_string(env, names[n], ERL_NIF_LATIN1),
                cap);
    }

    free(names);

    return enif_make_tuple2(env,
            atom_ok,
            cap);

ERR:
    free(names);
    return verterr(env);
}
    ERL_NIF_TERM
vert_virStoragePoolLookupByVolume(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    VERT_RESOURCE *vp = NULL;
    VERT_RESOURCE *pp = NULL;


    VERT_GET_RESOURCE(0, vp, VERT_RES_STORAGEVOL);

    VERT_RES_ALLOC(pp, VERT_RES_STORAGEPOOL, vp->conn);

    pp->res = virStoragePoolLookupByVolume(vp->res);

    if (pp->res == NULL) {
        enif_release_resource(pp);
        return verterr(env);
    }

    return vert_make_resource(env, pp, atom_storagepool);
}