打开原始磁盘并获取 OS X 的大小

10

使用以下代码,我能够成功地在我的机器上打开原始磁盘,但是当我获取磁盘长度时,每次都会得到0...

// Where "Path" is /dev/rdisk1 -- is rdisk1 versus disk1 the proper way to open a raw disk?
Device = open(Path, O_RDWR);
if (Device == -1)
{
    throw xException("Error opening device");
}

使用这两种方法获取大小都会返回0:

struct stat st;

if (stat(Path, &st) == 0)
    _Length = st.st_size;

这是一个简单的HTML段落,其中只包含斜杠字符“/”。
_Length = (INT64)lseek(Device, 0, SEEK_END);
        lseek(Device, 0, SEEK_SET);

我不太熟悉在非Windows平台上进行编程,所以请原谅任何看起来奇怪的地方。我的问题如下:

  1. 这是在Mac OS X下打开原始磁盘的正确方法吗?
  2. 可能导致返回磁盘大小为0的原因是什么?

涉及的磁盘是未格式化的磁盘,但对于那些想从磁盘工具中获取信息的人(已删除非重要内容):

Name :  ST920217 AS Media
Type :  Disk

Partition Map Scheme :  Unformatted
Disk Identifier      :  disk1
Media Name           :  ST920217 AS Media
Media Type           :  Generic
Writable             :  Yes
Total Capacity       :  20 GB (20,003,880,960 Bytes)
Disk Number          :  1
Partition Number     :  0

虽然直接访问原始磁盘是一种不错的方式,但像这样获取大小可能不起作用(此外,您应该首先尝试使用lseek64)。可以尝试使用ioctlfcntl来获取大小,否则您必须通过某些特殊的OSX特定函数来获取信息。 - Some programmer dude
@JoachimPileborg,我已经定义了_FILE_OFFSET_BITS 64 ... 这些不是相同的吗? - Lander
@JoachimPileborg 正在执行:lseek(Device, 0x7FFFFFFF - 1, SEEK_SET) 实际上返回的是0x7FFFFFFE,因此要么是位被丢弃了,要么是磁盘不支持 lseek(..., 0, SEEK_END);,但据我所知它们应该支持。编辑:我不知道为什么之前没有执行 lseek(Device, 0xFFFFFFFF + 5, SEEK_SET),但那会返回4,所以我认为是位被丢弃了。 - Lander
好的。我今天出门后意识到自己状态不佳。0xFFFFFFFF + 5因为位溢出(没有将其转换为INT64)而产生了4。当我直接寻找到“20003880960L”时,我的应用程序输出“磁盘成功打开。长度:0x4A8530000”。对于造成的混淆非常抱歉... - Lander
@Lander:您是否愿意编辑或简要回答自己的问题呢? - Jirka Hanika
显示剩余2条评论
1个回答

8

在搜索ioctl请求代码时,我找到了一些实际有效的内容。

#include <sys/disk.h>
#include <sys/ioctl.h>
#include <fcntl.h>

int main()
{
    // Open disk
    uint32_t dev = open("/dev/disk1", O_RDONLY);

    if (dev == -1) {
        perror("Failed to open disk");
        return -1;
    }

    uint64_t sector_count = 0;
    // Query the number of sectors on the disk
    ioctl(dev, DKIOCGETBLOCKCOUNT, &sector_count);

    uint32_t sector_size = 0;
    // Query the size of each sector
    ioctl(dev, DKIOCGETBLOCKSIZE, &sector_size);

    uint64_t disk_size = sector_count * sector_size;
    printf("%ld", disk_size);
    return 0;
}

这样的代码应该就可以解决问题了。我只是将我拥有的代码复制到了那里,所以我不确定它是否会编译通过,但是应该可以。


实际上,它不会像那样工作 - 无符号整数扇区至少需要是无符号长整型,否则第一个ioctl将导致其他堆栈变量被破坏(使用默认编译器设置和相对较小的磁盘进行探测时,“dev”将被写入零)更恰当地说,这些变量需要是sys/disk.h中数据结构所规定的uint64_t和uint32_t。 - kert
@Lander,我正在尝试你的代码,但是在“open”处总是出现错误,你知道可能的原因吗? - RuLoViC
@RuLoViC 可能与 系统完整性保护 有关,或者您需要以 root 用户身份运行应用程序。映射错误代码将为您提供更好的想法。系统调用将设置 errno,然后您可以将其与此处的值进行比较 here - Lander
如何正确地解决SIP问题?我试图打开一个设备(外部USB硬盘),但即使是root用户,MacOS(10.1.4.2)也不会给我访问权限。 - Hanzaplastique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接