#include "physicaldisk.h"
#if __has_include(<libgeom.h>)
#include "util/stringUtils.h"
#include <devstat.h>
#include <memory.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/disk.h>
#include <libgeom.h>
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
{
struct gmesh geomTree;
if (geom_gettree(&geomTree) < 0)
return "geom_gettree() failed";
if (geom_stats_open() < 0)
return "geom_stats_open() failed";
void* snap = geom_stats_snapshot_get();
struct devstat* snapIter;
while ((snapIter = geom_stats_snapshot_next(snap)) != NULL)
{
if (snapIter->device_type & DEVSTAT_TYPE_PASS)
continue;
struct gident* geomId = geom_lookupid(&geomTree, snapIter->id);
if (geomId == NULL)
continue;
if (geomId->lg_what != ISPROVIDER)
continue;
struct gprovider* provider = (struct gprovider*) geomId->lg_ptr;
if (provider->lg_geom->lg_rank != 1)
continue;
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(provider->lg_name);
FF_STRBUF_AUTO_DESTROY identifier = ffStrbufCreate();
FFPhysicalDiskType type = FF_PHYSICALDISK_TYPE_NONE;
for (struct gconfig* ptr = provider->lg_config.lh_first; ptr; ptr = ptr->lg_config.le_next)
{
if (ffStrEquals(ptr->lg_name, "descr"))
ffStrbufSetS(&name, ptr->lg_val);
else if (ffStrEquals(ptr->lg_name, "rotationrate") && !ffStrEquals(ptr->lg_val, "unknown"))
type |= ffStrEquals(ptr->lg_val, "0") ? FF_PHYSICALDISK_TYPE_SSD : FF_PHYSICALDISK_TYPE_HDD;
else if (ffStrEquals(ptr->lg_name, "ident"))
ffStrbufSetS(&identifier, ptr->lg_val);
else if (ffStrEquals(ptr->lg_name, "access"))
{
if (ffStrEquals(ptr->lg_val, "read-only"))
type |= FF_PHYSICALDISK_TYPE_READONLY;
else if (ffStrEquals(ptr->lg_val, "read-write"))
type |= FF_PHYSICALDISK_TYPE_READWRITE;
}
}
if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix))
continue;
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name);
ffStrbufInitMove(&device->serial, &identifier);
ffStrbufTrim(&device->serial, ' ');
ffStrbufInit(&device->revision);
ffStrbufInit(&device->interconnect);
switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK)
{
case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break;
case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break;
case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break;
case 0x040 : ffStrbufAppendS(&device->interconnect, "NVMe"); break;
}
device->size = (uint64_t) provider->lg_mediasize;
ffStrbufInitMove(&device->name, &name);
if (!(device->type & FF_PHYSICALDISK_TYPE_READONLY) && !(device->type & FF_PHYSICALDISK_TYPE_READWRITE))
{
int acr = 1, acw = 1; if (sscanf(provider->lg_mode, "r%dw%de%*d", &acr, &acw) == 2 && acr)
type |= acw ? FF_PHYSICALDISK_TYPE_READWRITE : FF_PHYSICALDISK_TYPE_READONLY;
}
device->type = type;
device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
}
geom_stats_snapshot_free(snap);
geom_stats_close();
return NULL;
}
#else
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
{
return "Fastfetch was compiled without libgeom support";
}
#endif