#include "zpool.h" #ifdef FF_HAVE_LIBZFS #include "util/kmod.h" #ifdef __sun #define FF_DISABLE_DLOPEN #include const char* zpool_get_state_str(zpool_handle_t* zpool) { if (zpool_get_state(zpool) == POOL_STATE_UNAVAIL) return "FAULTED"; else { const char *str; zpool_errata_t errata; zpool_status_t status = zpool_get_status(zpool, (char**) &str, &errata); if (status == ZPOOL_STATUS_IO_FAILURE_WAIT || status == ZPOOL_STATUS_IO_FAILURE_CONTINUE || status == ZPOOL_STATUS_IO_FAILURE_MMP) return "SUSPENDED"; else { nvlist_t *nvroot = fnvlist_lookup_nvlist(zpool_get_config(zpool, NULL), ZPOOL_CONFIG_VDEV_TREE); uint_t vsc; vdev_stat_t *vs; #ifdef __x86_64__ if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, (uint64_t**) &vs, &vsc) != 0) #else if (nvlist_lookup_uint32_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, (uint32_t**) &vs, &vsc) != 0) #endif return "UNKNOWN"; else return zpool_state_to_name(vs->vs_state, vs->vs_aux); } } } #else #include "libzfs_simplified.h" #endif #include "common/library.h" typedef struct FFZfsData { FF_LIBRARY_SYMBOL(libzfs_fini) FF_LIBRARY_SYMBOL(zpool_iter) FF_LIBRARY_SYMBOL(zpool_get_prop_int) FF_LIBRARY_SYMBOL(zpool_get_name) FF_LIBRARY_SYMBOL(zpool_get_state_str) libzfs_handle_t* handle; FFlist* result; } FFZfsData; static inline void cleanLibzfs(FFZfsData* data) { if (data->fflibzfs_fini && data->handle) { data->fflibzfs_fini(data->handle); data->handle = NULL; } } static int enumZpoolCallback(zpool_handle_t* zpool, void* param) { FFZfsData* data = (FFZfsData*) param; zprop_source_t source; FFZpoolResult* item = ffListAdd(data->result); ffStrbufInitS(&item->name, data->ffzpool_get_name(zpool)); ffStrbufInitS(&item->state, data->ffzpool_get_state_str(zpool)); item->version = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_VERSION, &source); item->total = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_SIZE, &source); item->used = item->total - data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FREE, &source); uint64_t fragmentation = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FRAGMENTATION, &source); item->fragmentation = fragmentation == UINT64_MAX ? 0.0/0.0 : (double) fragmentation; return 0; } const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */) { FF_LIBRARY_LOAD(libzfs, "dlopen libzfs" FF_LIBRARY_EXTENSION " failed", "libzfs" FF_LIBRARY_EXTENSION, 4); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, libzfs_init); libzfs_handle_t* handle = fflibzfs_init(); if (!handle) { if (!ffKmodLoaded("zfs")) return "`zfs` kernel module is not loaded"; return "libzfs_init() failed"; } __attribute__((__cleanup__(cleanLibzfs))) FFZfsData data = { .handle = handle, .result = result, }; FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, zpool_iter); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, libzfs_fini); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_prop_int); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_name); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_state_str); if (ffzpool_iter(handle, enumZpoolCallback, &data) < 0) return "zpool_iter() failed"; return NULL; } #else const char* ffDetectZpool(FF_MAYBE_UNUSED FFlist* result) { return "Fastfetch was compiled without libzfs support"; } #endif