summaryrefslogtreecommitdiffstats
path: root/src/detection/physicaldisk/physicaldisk_bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/physicaldisk/physicaldisk_bsd.c')
-rw-r--r--src/detection/physicaldisk/physicaldisk_bsd.c127
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