如何使用C / C ++在OS X中获得分区偏移?

cha*_*m15 1 c c++ macos

我想使用驱动器序列号+分区偏移量+分区大小来创建自己的卷ID,但是我需要知道如何在OS X上获取分区信息。我(成功地)尝试了以下操作:


int fd;
if ((fd = open("/dev/disk0s1", O_RDONLY|O_NONBLOCK)) >= 0) {
    struct hd_geometry geom;
    if (ioctl(fd, 0x0301, &geom) == 0){ //0x0301 is HDIO_GETGEO
        printf("Index = %u\n", geom.start);
    }
    close(fd);
}
Run Code Online (Sandbox Code Playgroud)

但是,即使是成功的,这是因为作为一个有缺陷的解决指出:hd_geometry.start是一个无符号长,“将不包含在大小的磁盘超过219千兆有意义的价值。” 此外,我相信它需要管理权限,这也是不好的。还有其他方法吗?

Ahm*_*sud 5

好吧,最后一点。由于您要读取原始磁盘,因此需要管理员权限。例如,您可能潜在地寻找写入私有密钥并以非特权用户身份读取它的块,那么我们将在哪里?

其次,/ dev / disk0s1只是一个分区,也是它的块设备版本。您需要读取磁盘的字符设备版本,该版本为/ dev / rdisk0。

第三,HDIO_GETGEO是一个Linux内核ioctl(尤其是考虑它的0x0301值),您不会因此而在Darwin上走得太远。看一下<sys/disk.h>相关的磁盘IOCTL。我认为DKIOCGETFEATURES / DKIOCGETPHYSICALBLOCKSIZE等应该可以助您一臂之力。

如果您对这些概念有疑问,我强烈建议您在可以破坏的虚拟机中进行此开发,因为您不希望意外使用会损坏磁盘的IOCTL。

附录(可能是答案)

GUID分区表

因此,您正在Mac OS X / Darwin上工作;我们假设GUID分区表

LBA ==逻辑块寻址...; 1块= 512字节

LBA 0 - Master Boot Record  (also contained old partition table) 
LBA 1 - GUID Partition Table (standard for OS X) 
LBA 2 - first 4 entries 
LBA 3 - 33 - next 124 entries making for a total of 128 entries
LBA 34 - Partition 1
Run Code Online (Sandbox Code Playgroud)

您可以抓住第二个区块并开始跟踪信息

阅读http://en.wikipedia.org/wiki/GUID_Partition_Table

它的定义很明确。GUID对整数值使用小尾数字节顺序(请参阅Wikipedia页面底部的示例)

测试建议

进行复制,以免损坏实际的磁盘:

dd if = / dev / rdisk0 of = fakedisk count = 33

这将创建前33个块或磁盘的副本。使用fakedisk测试您的程序。

MBR

如果您的磁盘使用MBR,请使用与GPT相同的概念

http://en.wikipedia.org/wiki/Master_Boot_Record

对各部门都有很好的描述。

使用dtruss fdisk -d / dev / rdisk0 dump获得提示

dstrings fdisk dump显示fdisk使用上述方法。

dtruss fdisk -d / dev / rdisk0

SYSCALL(args)            = return
open("/dev/dtracehelper\0", 0x2, 0x7FFF5CFDD5C0)                 = 3 0
__sysctl(0x7FFF5CFDD084, 0x2, 0x7FFF5CFDD070)            = 0 0
bsdthread_register(0x7FFF8BCA41D4, 0x7FFF8BCA41C4, 0x2000)               = 0 0
[[ .... content edited  ... ]]
open("/dev/rdisk0\0", 0x0, 0x7FFF5CFDDD7A)               = 3 0
fstat64(0x3, 0x7FFF5CFDDA10, 0x0)                = 0 0
fstat64(0x3, 0x7FFF5CFDDAC8, 0x0)                = 0 0
ioctl(0x3, 0x40086419, 0x7FFF5CFDDB60)           = 0 0
ioctl(0x3, 0x40046418, 0x7FFF5CFDDB5C)           = 0 0
close(0x3)               = 0 0
open("/dev/rdisk0\0", 0x0, 0x0)          = 3 0
fstat64(0x3, 0x7FFF5CFDDAD0, 0x0)                = 0 0
open("/dev/rdisk0\0", 0x0, 0x0)          = 4 0
fstat64(0x4, 0x7FFF5CFDDA80, 0x0)                = 0 0
lseek(0x4, 0x0, 0x0)             = 0 0
issetugid(0x102C22000, 0x3, 0x7FFF5CFDDC00)              = 0 0
geteuid(0x102C22000, 0x3, 0x0)           = 0 0
[[ tracing data suppressed ]]
read(0x4, "\0", 0x200)           = 512 0
close(0x4)               = 0 0
getrlimit(0x1008, 0x7FFF5CFDCFA8, 0x7FFF8BD0D470)                = 0 0
fstat64(0x1, 0x7FFF5CFDCEF8, 0x7FFF5CFDCFBC)             = 0 0
ioctl(0x1, 0x4004667A, 0x7FFF5CFDCF94)           = 0 0
write_nocancel(0x1, "1,625142447,0xEE,-,1023,254,63,1023,254,63\n\0", 0x2B)              = 43 0
write_nocancel(0x1, "0,0,0x00,-,0,0,0,0,0,0\n\0", 0x17)          = 23 0
write_nocancel(0x1, "0,0,0x00,-,0,0,0,0,0,0\n\0", 0x17)          = 23 0
write_nocancel(0x1, "0,0,0x00,-,0,0,0,0,0,0\n\0", 0x17)          = 23 0
close(0x3)               = 0 0
Run Code Online (Sandbox Code Playgroud)

解密八卦

我如何确定使用的是这些ioctl。

dtruss转储为:

ioctl(0x3,0x40086419,0x7FFF5CFDDB60)= 0 0 ioctl(0x3,0x40046418,0x7FFF5CFDDB5C)= 0 0

0x40086518对应于DKIOCGETBLOCKSIZE,这是通过回溯disk.h来收集的(注意_IOR在ioccom.h中扩展为_IOC),并且后8位对应于IOCTL常量定义中的第二个数字。

#define DKIOCGETBLOCKSIZE _IOR('d', 24, uint32_t)

在0x40086418中尾随的18(十六进制)== 24(十进制)

因此,现在我们注意到fdisk执行DKIOCGETBLOCKCOUNT和DKIOCGETBLOCKSIZE来获取物理范围,因为从技术上讲,您应该使用该结果来找出LBA偏移量(请参阅下面的解密ioctl)

实际读入fdisk

这是fdisk的执行方式:

打开(“ / dev / rdisk0 \ 0”,0x0,0x0)= 4 0读取(0x4,“ \ 0”,0x200)= 512 0关闭(0x4)= 0 0

您可以按照以下步骤操作,确保将0x200替换为实际的块大小。

另外,如果您要使用上面的dd命令进行复制,请使用此处显示的块大小。