github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/system/disk/iostat_darwin.c (about) 1 // https://github.com/lufia/iostat/blob/9f7362b77ad333b26c01c99de52a11bdb650ded2/iostat_darwin.c 2 #include <stdint.h> 3 #include <CoreFoundation/CoreFoundation.h> 4 #include "iostat_darwin.h" 5 6 #define IOKIT 1 /* to get io_name_t in device_types.h */ 7 8 #include <IOKit/IOKitLib.h> 9 #include <IOKit/storage/IOBlockStorageDriver.h> 10 #include <IOKit/storage/IOMedia.h> 11 #include <IOKit/IOBSD.h> 12 13 #include <mach/mach_host.h> 14 15 static int getdrivestat(io_registry_entry_t d, DriveStats *stat); 16 static int fillstat(io_registry_entry_t d, DriveStats *stat); 17 18 int 19 readdrivestat(DriveStats a[], int n) 20 { 21 mach_port_t port; 22 CFMutableDictionaryRef match; 23 io_iterator_t drives; 24 io_registry_entry_t d; 25 kern_return_t status; 26 int na, rv; 27 28 IOMasterPort(bootstrap_port, &port); 29 match = IOServiceMatching("IOMedia"); 30 CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); 31 status = IOServiceGetMatchingServices(port, match, &drives); 32 if(status != KERN_SUCCESS) 33 return -1; 34 35 na = 0; 36 while(na < n && (d=IOIteratorNext(drives)) > 0){ 37 rv = getdrivestat(d, &a[na]); 38 if(rv < 0) 39 return -1; 40 if(rv > 0) 41 na++; 42 IOObjectRelease(d); 43 } 44 IOObjectRelease(drives); 45 return na; 46 } 47 48 static int 49 getdrivestat(io_registry_entry_t d, DriveStats *stat) 50 { 51 io_registry_entry_t parent; 52 kern_return_t status; 53 CFDictionaryRef props; 54 CFStringRef name; 55 CFNumberRef num; 56 int rv; 57 58 memset(stat, 0, sizeof *stat); 59 status = IORegistryEntryGetParentEntry(d, kIOServicePlane, &parent); 60 if(status != KERN_SUCCESS) 61 return -1; 62 if(!IOObjectConformsTo(parent, "IOBlockStorageDriver")){ 63 IOObjectRelease(parent); 64 return 0; 65 } 66 67 status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions); 68 if(status != KERN_SUCCESS){ 69 IOObjectRelease(parent); 70 return -1; 71 } 72 name = (CFStringRef)CFDictionaryGetValue(props, CFSTR(kIOBSDNameKey)); 73 CFStringGetCString(name, stat->name, NAMELEN, CFStringGetSystemEncoding()); 74 num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaSizeKey)); 75 CFNumberGetValue(num, kCFNumberSInt64Type, &stat->size); 76 num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaPreferredBlockSizeKey)); 77 CFNumberGetValue(num, kCFNumberSInt64Type, &stat->blocksize); 78 CFRelease(props); 79 80 rv = fillstat(parent, stat); 81 IOObjectRelease(parent); 82 if(rv < 0) 83 return -1; 84 return 1; 85 } 86 87 static struct { 88 char *key; 89 size_t off; 90 } statstab[] = { 91 {kIOBlockStorageDriverStatisticsBytesReadKey, offsetof(DriveStats, read)}, 92 {kIOBlockStorageDriverStatisticsBytesWrittenKey, offsetof(DriveStats, written)}, 93 {kIOBlockStorageDriverStatisticsReadsKey, offsetof(DriveStats, nread)}, 94 {kIOBlockStorageDriverStatisticsWritesKey, offsetof(DriveStats, nwrite)}, 95 {kIOBlockStorageDriverStatisticsTotalReadTimeKey, offsetof(DriveStats, readtime)}, 96 {kIOBlockStorageDriverStatisticsTotalWriteTimeKey, offsetof(DriveStats, writetime)}, 97 {kIOBlockStorageDriverStatisticsLatentReadTimeKey, offsetof(DriveStats, readlat)}, 98 {kIOBlockStorageDriverStatisticsLatentWriteTimeKey, offsetof(DriveStats, writelat)}, 99 }; 100 101 static int 102 fillstat(io_registry_entry_t d, DriveStats *stat) 103 { 104 CFDictionaryRef props, v; 105 CFNumberRef num; 106 kern_return_t status; 107 typeof(statstab[0]) *bp, *ep; 108 109 status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions); 110 if(status != KERN_SUCCESS) 111 return -1; 112 v = (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOBlockStorageDriverStatisticsKey)); 113 if(v == NULL){ 114 CFRelease(props); 115 return -1; 116 } 117 118 ep = &statstab[sizeof(statstab)/sizeof(statstab[0])]; 119 for(bp = &statstab[0]; bp < ep; bp++){ 120 CFStringRef s; 121 122 s = CFStringCreateWithCString(kCFAllocatorDefault, bp->key, CFStringGetSystemEncoding()); 123 num = (CFNumberRef)CFDictionaryGetValue(v, s); 124 if(num) 125 CFNumberGetValue(num, kCFNumberSInt64Type, ((char*)stat)+bp->off); 126 CFRelease(s); 127 } 128 129 CFRelease(props); 130 return 0; 131 }