Reputation: 1631
I want to find out what is block file size under MacOs. In my example I try to determine /dev/disk0:
diskutil info /dev/disk0
Device Identifier: disk0
Device Node: /dev/disk0
Whole: Yes
Part of Whole: disk0
Device / Media Name: APPLE SSD SD0128F
Volume Name: Not applicable (no file system)
Mounted: Not applicable (no file system)
File System: None
Content (IOContent): GUID_partition_scheme
OS Can Be Installed: No
Media Type: Generic
Protocol: PCI
SMART Status: Verified
Disk Size: 121.3 GB (121332826112 Bytes) (exactly 236978176 512-Byte-Units)
Diskutil gives correct size "123.3 GB". Now the same thing using statfs:(https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/statfs.2.html#//apple_ref/doc/man/2/statfs):
#include <iostream>
#include <sys/param.h>
#include <sys/mount.h>
int main()
{
struct statfs s;
statfs("/dev/disk0", &s);
std::cout << s.f_bsize * s.f_blocks << " B\n";
}
Output: 196096 B
Upvotes: 2
Views: 1338
Reputation: 26527
If you want the total size of the device, try this :
// gcc -Wall -framework Foundation -framework DiskArbitration disk_size.m -o disk_size
// Call method : ./disk_size /dev/disk0
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
DASessionRef session = DASessionCreate(NULL);
DADiskRef disk = DADiskCreateFromBSDName(NULL, session, argv[1]);
CFDictionaryRef diskDescription = DADiskCopyDescription(disk);
NSDictionary *diskData = (NSDictionary *)diskDescription;
NSString *diskSizeKey = (NSString *)kDADiskDescriptionMediaSizeKey;
unsigned long size = [[diskData objectForKey:diskSizeKey] unsignedLongValue];
NSLog(@"size in bytes = %lu", size);
CFRelease(diskDescription);
CFRelease(disk);
CFRelease(session);
exit(EXIT_SUCCESS);
}
Upvotes: 0
Reputation: 4487
OK, the original question is weird. Since as nanofarad already stated that we should pass statfs
with the path name of any file or directory within the mounted file system instead of the device's bsdname(like /dev/disk1s1).
I saw the the question from Matt:
A way to get the block or "fragment" size for the device on a given path is on (usually from statfs on Linux, but relevant fields seem to be missing on Darwin?).
I presume you are asking "Given a file path, how to get the block size of its physical device?"
Well if so, macOS has a high-level API for this. It's the DiskArbitration
framework.
It has a function DADiskCreateFromVolumePath
which can get Disk object from any path. Apple Document Here
So to get the block size for the device on a given path is on, you can use below code.
#include <iostream>
#include <DiskArbitration/DADisk.h> //Import DiskArbitration.framework&CoreFoundation.framework in xcode first
#include <DiskArbitration/DASession.h>
#define PATH "/"
int main(int argc, const char * argv[]) {
//Create DASession
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
//Create URL from file path
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
CFSTR(PATH),
kCFURLPOSIXPathStyle,
true);
//Get path's physical disk
DADiskRef diskRef = DADiskCreateFromVolumePath(kCFAllocatorDefault,
session,
url);
//Acquire all disk info, see the screenshot below.
CFDictionaryRef infoRef = DADiskCopyDescription(diskRef);
}
and below is all the info I get from the build-in apfs disk partition:
It has a device block size of 4096 bytes.
Upvotes: 1
Reputation: 41281
The documentation of statfs
is as follows:
Statfs() returns information about a mounted file system. Path is the path name of any file within the mounted file system. Buf is a pointer to a statfs or statfs64 structure defined as follows...
You are passing /dev/disk0
as the path, which will give you the size of whatever filesystem represents /dev
, which is likely some sort of devtmpfs. Your path should be a filename or path within the filesystem held on /dev/disk0
, not the block device itself.
Issue IOCTLs as documented:
int fd = open("/dev/whatever", O_RDONLY);
if(fd < 0) {
// error handling
}
uint64_t count;
if(ioctl(fd, DKIOCGETBLOCKCOUNT, &count) < 0) {
// error handling
}
uint32_t bsize;
if(ioctl(fd, DKIOCGETBLOCKSIZE, &bsize) < 0) {
// error handling
}
return count * bsize;
Upvotes: 2