#include "physicaldisk.h" #if __has_include() #include "common/strutil.h" #include #include #include #include #include #include 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