mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-07 21:50:08 +01:00
PhysicalDisk: add new module
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef enum FFPhysicalDiskType
|
||||
{
|
||||
FF_PHYSICALDISK_TYPE_NONE = 0,
|
||||
|
||||
// If neither is set, it's unknown
|
||||
FF_PHYSICALDISK_TYPE_HDD = 1 << 0,
|
||||
FF_PHYSICALDISK_TYPE_SSD = 1 << 1,
|
||||
|
||||
FF_PHYSICALDISK_TYPE_FIXED = 1 << 2,
|
||||
FF_PHYSICALDISK_TYPE_REMOVABLE = 1 << 3,
|
||||
} FFPhysicalDiskType;
|
||||
|
||||
typedef struct FFPhysicalDiskResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf interconnect;
|
||||
FFstrbuf serial;
|
||||
FFstrbuf devPath;
|
||||
FFPhysicalDiskType type;
|
||||
uint64_t size;
|
||||
} FFPhysicalDiskResult;
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options);
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "physicaldisk.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOBSD.h>
|
||||
#include <IOKit/storage/IOMedia.h>
|
||||
#include <IOKit/storage/IOBlockStorageDriver.h>
|
||||
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
|
||||
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
|
||||
|
||||
static inline void wrapIoObjectRelease(io_service_t* service)
|
||||
{
|
||||
assert(service);
|
||||
if (*service)
|
||||
IOObjectRelease(*service);
|
||||
}
|
||||
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
|
||||
|
||||
io_name_t deviceName;
|
||||
if (IORegistryEntryGetName(registryEntry, deviceName) != KERN_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDriver = 0;
|
||||
if (IORegistryEntryGetParentEntry(entryPartition, kIOServicePlane, &entryDriver) != KERN_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!IOObjectConformsTo(entryDriver, kIOBlockStorageDriverClass)) // physical disk only
|
||||
continue;
|
||||
|
||||
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInitS(&device->name, deviceName);
|
||||
ffStrbufInit(&device->devPath);
|
||||
ffStrbufInit(&device->interconnect);
|
||||
device->type = FF_PHYSICALDISK_TYPE_NONE;
|
||||
device->size = 0;
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFBooleanRef removable = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaRemovableKey), kCFAllocatorDefault, kNilOptions);
|
||||
device->type |= CFBooleanGetValue(removable) ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED;
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef bsdName = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (bsdName)
|
||||
{
|
||||
ffCfStrGetString(bsdName, &device->devPath);
|
||||
ffStrbufPrependS(&device->devPath, "/dev/");
|
||||
}
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFNumberRef mediaSize = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaSizeKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (mediaSize)
|
||||
ffCfNumGetInt64(mediaSize, (int64_t*) &device->size);
|
||||
else
|
||||
device->size = 0;
|
||||
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0;
|
||||
if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS)
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (protocolCharacteristics)
|
||||
ffCfDictGetString(protocolCharacteristics, CFSTR(kIOPropertyPhysicalInterconnectTypeKey), &device->interconnect);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (deviceCharacteristics)
|
||||
{
|
||||
ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductSerialNumberKey), &device->serial);
|
||||
|
||||
CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey));
|
||||
if (mediumType)
|
||||
{
|
||||
if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0)
|
||||
device->type |= FF_PHYSICALDISK_TYPE_SSD;
|
||||
else if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0)
|
||||
device->type |= FF_PHYSICALDISK_TYPE_HDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "physicaldisk.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);
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
device->size = (uint64_t) provider->lg_mediasize;
|
||||
ffStrbufInitMove(&device->name, &name);
|
||||
device->type = type;
|
||||
}
|
||||
|
||||
geom_stats_snapshot_free(snap);
|
||||
geom_stats_close();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "physicaldisk.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/");
|
||||
if(sysBlockDirp == NULL)
|
||||
return "opendir(\"/sys/block/\") == NULL";
|
||||
|
||||
struct dirent* sysBlockEntry;
|
||||
while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL)
|
||||
{
|
||||
const char* const devName = sysBlockEntry->d_name;
|
||||
|
||||
if (devName[0] == '.')
|
||||
continue;
|
||||
|
||||
char pathSysBlock[PATH_MAX];
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s", devName);
|
||||
|
||||
char pathSysDeviceReal[PATH_MAX] = "";
|
||||
readlink(pathSysBlock, pathSysDeviceReal, sizeof(pathSysDeviceReal) - 1);
|
||||
|
||||
if (strstr(pathSysDeviceReal, "/virtual/")) // virtual device
|
||||
continue;
|
||||
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device", devName);
|
||||
if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY))
|
||||
continue;
|
||||
|
||||
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
|
||||
device->type = FF_PHYSICALDISK_TYPE_NONE;
|
||||
ffStrbufInit(&device->name);
|
||||
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName);
|
||||
ffAppendFileBuffer(pathSysBlock, &device->name);
|
||||
if (device->name.length > 0)
|
||||
ffStrbufAppendC(&device->name, ' ');
|
||||
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName);
|
||||
ffAppendFileBuffer(pathSysBlock, &device->name);
|
||||
ffStrbufTrim(&device->name, ' ');
|
||||
|
||||
if (device->name.length == 0)
|
||||
ffStrbufSetS(&device->name, devName);
|
||||
|
||||
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
result->length--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufInitF(&device->devPath, "/dev/%s", devName);
|
||||
|
||||
{
|
||||
ffStrbufInit(&device->interconnect);
|
||||
if (strstr(pathSysDeviceReal, "/usb") != NULL)
|
||||
ffStrbufSetS(&device->interconnect, "usb");
|
||||
else
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName);
|
||||
if (!ffAppendFileBuffer(pathSysBlock, &device->interconnect))
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/uevent", devName);
|
||||
if (ffParsePropFile(pathSysBlock, "DEVTYPE=", &device->interconnect))
|
||||
ffStrbufSubstrBeforeLastC(&device->interconnect, '_');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName);
|
||||
char isRotationalChar = '1';
|
||||
if (ffReadFileData(pathSysBlock, 1, &isRotationalChar) > 0)
|
||||
device->type |= isRotationalChar == '1' ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD;
|
||||
}
|
||||
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/size", devName);
|
||||
char blkSize[32];
|
||||
ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(blkSize) - 1, blkSize);
|
||||
if (fileSize > 0)
|
||||
{
|
||||
blkSize[fileSize] = 0;
|
||||
device->size = (uint64_t) strtoul(blkSize, NULL, 10) * 512;
|
||||
}
|
||||
else
|
||||
device->size = 0;
|
||||
}
|
||||
|
||||
{
|
||||
char removableChar = '0';
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/removable", devName);
|
||||
if (ffReadFileData(pathSysBlock, 1, &removableChar) > 0)
|
||||
device->type |= removableChar == '1' ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED;
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufInit(&device->serial);
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/serial", devName);
|
||||
ffReadFileBuffer(pathSysBlock, &device->serial);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "physicaldisk.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
{
|
||||
wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive";
|
||||
wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive");
|
||||
for (uint32_t idev = 0; ; ++idev)
|
||||
{
|
||||
_ultow(idev, pNum, 10);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
DWORD retSize;
|
||||
char sddBuffer[4096];
|
||||
if(!DeviceIoControl(
|
||||
hDevice,
|
||||
IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
&(STORAGE_PROPERTY_QUERY) {
|
||||
.PropertyId = StorageDeviceProperty,
|
||||
.QueryType = PropertyStandardQuery,
|
||||
},
|
||||
sizeof(STORAGE_PROPERTY_QUERY),
|
||||
&sddBuffer,
|
||||
sizeof(sddBuffer),
|
||||
&retSize,
|
||||
NULL
|
||||
) || retSize == 0)
|
||||
continue;
|
||||
|
||||
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
|
||||
device->type = FF_PHYSICALDISK_TYPE_NONE;
|
||||
STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer;
|
||||
|
||||
ffStrbufInit(&device->name);
|
||||
if (sdd->VendorIdOffset != 0)
|
||||
{
|
||||
ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset);
|
||||
ffStrbufTrim(&device->name, ' ');
|
||||
}
|
||||
if (sdd->ProductIdOffset != 0)
|
||||
{
|
||||
if (device->name.length)
|
||||
ffStrbufAppendC(&device->name, ' ');
|
||||
|
||||
ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset);
|
||||
ffStrbufTrimRight(&device->name, ' ');
|
||||
}
|
||||
|
||||
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
result->length--;
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufInitWS(&device->devPath, szDevice);
|
||||
ffStrbufInit(&device->serial);
|
||||
if (sdd->SerialNumberOffset != 0)
|
||||
{
|
||||
ffStrbufSetS(&device->serial, (const char*) sddBuffer + sdd->SerialNumberOffset);
|
||||
ffStrbufTrim(&device->serial, ' ');
|
||||
}
|
||||
|
||||
device->type |= sdd->RemovableMedia ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED;
|
||||
|
||||
ffStrbufInit(&device->interconnect);
|
||||
switch (sdd->BusType)
|
||||
{
|
||||
case BusTypeUnknown: ffStrbufSetStatic(&device->interconnect, "Unknown"); break;
|
||||
case BusTypeScsi: ffStrbufSetStatic(&device->interconnect, "Scsi"); break;
|
||||
case BusTypeAtapi: ffStrbufSetStatic(&device->interconnect, "Atapi"); break;
|
||||
case BusTypeAta: ffStrbufSetStatic(&device->interconnect, "Ata"); break;
|
||||
case BusType1394: ffStrbufSetStatic(&device->interconnect, "1394"); break;
|
||||
case BusTypeSsa: ffStrbufSetStatic(&device->interconnect, "Ssa"); break;
|
||||
case BusTypeFibre: ffStrbufSetStatic(&device->interconnect, "Fibra"); break;
|
||||
case BusTypeUsb: ffStrbufSetStatic(&device->interconnect, "Usb"); break;
|
||||
case BusTypeRAID: ffStrbufSetStatic(&device->interconnect, "RAID"); break;
|
||||
case BusTypeiScsi: ffStrbufSetStatic(&device->interconnect, "iScsi"); break;
|
||||
case BusTypeSas: ffStrbufSetStatic(&device->interconnect, "Sas"); break;
|
||||
case BusTypeSata: ffStrbufSetStatic(&device->interconnect, "Sata"); break;
|
||||
case BusTypeSd: ffStrbufSetStatic(&device->interconnect, "Sd"); break;
|
||||
case BusTypeMmc: ffStrbufSetStatic(&device->interconnect, "Mmc"); break;
|
||||
case BusTypeVirtual: ffStrbufSetStatic(&device->interconnect, "Virtual"); break;
|
||||
case BusTypeFileBackedVirtual: ffStrbufSetStatic(&device->interconnect, "FileBackedVirtual"); break;
|
||||
case BusTypeSpaces: ffStrbufSetStatic(&device->interconnect, "Spaces"); break;
|
||||
case BusTypeNvme: ffStrbufSetStatic(&device->interconnect, "Nvme"); break;
|
||||
case BusTypeSCM: ffStrbufSetStatic(&device->interconnect, "SCM"); break;
|
||||
case BusTypeUfs: ffStrbufSetStatic(&device->interconnect, "Ufs"); break;
|
||||
default: ffStrbufSetF(&device->interconnect, "Unknown (%d)", (int) sdd->BusType); break;
|
||||
}
|
||||
|
||||
DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {};
|
||||
if(DeviceIoControl(
|
||||
hDevice,
|
||||
IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
&(STORAGE_PROPERTY_QUERY) {
|
||||
.PropertyId = StorageDeviceSeekPenaltyProperty,
|
||||
.QueryType = PropertyStandardQuery,
|
||||
},
|
||||
sizeof(STORAGE_PROPERTY_QUERY),
|
||||
&dspd,
|
||||
sizeof(dspd),
|
||||
&retSize,
|
||||
NULL
|
||||
) && retSize == sizeof(dspd))
|
||||
device->type |= dspd.IncursSeekPenalty ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD;
|
||||
|
||||
DISK_GEOMETRY_EX dge = {};
|
||||
if(DeviceIoControl(
|
||||
hDevice,
|
||||
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
||||
NULL,
|
||||
0,
|
||||
&dge,
|
||||
sizeof(dge),
|
||||
&retSize,
|
||||
NULL))
|
||||
device->size = (uint64_t) dge.DiskSize.QuadPart;
|
||||
else
|
||||
device->size = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user