Here's the code to get the native block size:
#include <sys/stat.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <CoreFoundation/CoreFoundation.h>
// look up device number with stat
struct stat stats;
if (stat(path, &stats) != 0) {
return;
}
// use st_rdev instead of st_dev if
// the path is a device (/dev/disk0)
int bsd_major = major(stats.st_dev);
int bsd_minor = minor(stats.st_dev);
CFTypeRef keys[2] = { CFSTR(kIOBSDMajorKey), CFSTR(kIOBSDMinorKey) };
CFTypeRef values[2];
values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bsd_major);
values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bsd_minor);
CFDictionaryRef matchingDictionary;
matchingDictionary = CFDictionaryCreate(kCFAllocatorDefault,
&keys, &values,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease(values[0]);
CFRelease(values[1]);
// IOServiceGetMatchingService uses up one reference to the dictionary
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
matchingDictionary);
if (!service) {
return;
}
CFNumberRef blockSizeProperty;
blockSizeProperty = (CFNumberRef)IORegistryEntryCreateCFProperty(service,
CFSTR(kIOMediaPreferredBlockSizeKey),
kCFAllocatorDefault, 0);
if (!blockSizeProperty) {
return;
}
int blockSize;
CFNumberGetValue(blockSizeProperty, kCFNumberIntType, &blockSize);
CFRelease(blockSizeProperty);
// blockSize is the native block size of the device