Skip to content

Commit 27581d9

Browse files
committed
Disk (macOS): detect physical type
1 parent 4a89b92 commit 27581d9

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/detection/disk/disk_bsd.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,65 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk)
2121
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
2222
}
2323
#elif __APPLE__
24+
#include "util/apple/cf_helpers.h"
25+
2426
#include <sys/attr.h>
2527
#include <unistd.h>
28+
#include <IOKit/IOKitLib.h>
29+
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
2630

2731
struct VolAttrBuf {
2832
uint32_t length;
2933
attrreference_t volNameRef;
3034
char volNameSpace[MAXPATHLEN];
3135
} __attribute__((aligned(4), packed));
3236

37+
void detectDiskType(FFDisk* disk) // Not thread safe
38+
{
39+
if (!ffStrbufStartsWithS(&disk->mountFrom, "/dev/disk")) return;
40+
41+
static uint8_t cache[100]; // disk_id => physical_type + 1
42+
const char* numStart = disk->mountFrom.chars + strlen("/dev/disk");
43+
char* numEnd = NULL;
44+
unsigned long diskId = strtoul(numStart, &numEnd, 10);
45+
if (numEnd == numStart || diskId >= 100)
46+
return;
47+
48+
if (cache[diskId])
49+
{
50+
disk->physicalType = cache[diskId] - 1;
51+
return;
52+
}
53+
54+
io_iterator_t iterator;
55+
char temp = *numEnd; *numEnd = '\0'; // Check for root disk directly
56+
CFMutableDictionaryRef matchDict = IOBSDNameMatching(MACH_PORT_NULL, 0, disk->mountFrom.chars + strlen("/dev/"));
57+
*numEnd = temp;
58+
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) == kIOReturnSuccess)
59+
{
60+
for (io_registry_entry_t registryEntry = IOIteratorNext(iterator); registryEntry; IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &registryEntry))
61+
{
62+
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = (CFDictionaryRef) IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
63+
if (!deviceCharacteristics)
64+
continue;
65+
66+
CFStringRef diskType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey));
67+
if (diskType)
68+
{
69+
if (CFStringCompare(diskType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0)
70+
disk->physicalType = FF_DISK_PHYSICAL_TYPE_SSD;
71+
else if (CFStringCompare(diskType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0)
72+
disk->physicalType = FF_DISK_PHYSICAL_TYPE_HDD;
73+
}
74+
break;
75+
}
76+
77+
IOObjectRelease(iterator);
78+
}
79+
80+
cache[diskId] = (uint8_t) (disk->physicalType + 1);
81+
}
82+
3383
void detectFsInfo(struct statfs* fs, FFDisk* disk)
3484
{
3585
if(fs->f_flags & MNT_DONTBROWSE)
@@ -45,6 +95,8 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk)
4595
.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME,
4696
}, &attrBuf, sizeof(attrBuf), 0) == 0)
4797
ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace);
98+
99+
detectDiskType(disk);
48100
}
49101
#endif
50102

0 commit comments

Comments
 (0)