diff options
Diffstat (limited to 'src/detection/physicaldisk/physicaldisk_bsd.c')
| -rw-r--r-- | src/detection/physicaldisk/physicaldisk_bsd.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c new file mode 100644 index 0000000..5a87768 --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -0,0 +1,127 @@ +#include "physicaldisk.h" + +#if __has_include(<libgeom.h>) + + #include "common/strutil.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; + } + + FFPhysicalDiskType type = FF_PHYSICALDISK_TYPE_NONE; + if (!ffStrEquals(provider->lg_geom->lg_class->lg_name, "DISK")) { + if (options->hideType & FF_PHYSICALDISK_TYPE_VIRTUAL) { + continue; + } + + type |= FF_PHYSICALDISK_TYPE_VIRTUAL; + } + uint64_t size = (uint64_t) provider->lg_mediasize; + if (size == 0) { + if (options->hideType & FF_PHYSICALDISK_TYPE_UNUSED) { + continue; + } + + type |= FF_PHYSICALDISK_TYPE_UNUSED; + } + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(provider->lg_name); + FF_STRBUF_AUTO_DESTROY identifier = ffStrbufCreate(); + 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 = FF_LIST_ADD(FFPhysicalDiskResult, *result); + ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name); + ffStrbufInitMove(&device->serial, &identifier); + ffStrbufTrimSpace(&device->serial); + ffStrbufInit(&device->revision); + ffStrbufInit(&device->interconnect); + ffStrbufInitMove(&device->name, &name); + device->size = size; + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; + + switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK) { + case DEVSTAT_TYPE_IF_SCSI: + ffStrbufSetStatic(&device->interconnect, "SCSI"); + break; + case DEVSTAT_TYPE_IF_IDE: + ffStrbufSetStatic(&device->interconnect, "IDE"); + break; + case DEVSTAT_TYPE_IF_OTHER: + ffStrbufSetStatic(&device->interconnect, "OTHER"); + break; + + // https://github.com/freebsd/freebsd-src/commit/d282baddb0b029ca8466d23ac51e95c918442535 + case 0x040 /*DEVSTAT_TYPE_IF_NVME*/: + ffStrbufSetStatic(&device->interconnect, "NVMe"); + break; + } + + if (!(device->type & FF_PHYSICALDISK_TYPE_READONLY) && !(device->type & FF_PHYSICALDISK_TYPE_READWRITE)) { + int acr = 1, acw = 1; // Number of partitions mounted for reading or writing + 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; + } + + 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 |