@@ -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
2731struct 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+
3383void 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