如何从 OS X 上的 CD 读取纯数据扇区 (Mode1)

How to read plain data sectors (Mode1) from a CD on OS X

我正在尝试从 OS X 上的数据 CD 读取普通 2048 字节大小的数据扇区。

但是当我打开诸如“/dev/disk8”之类的设备时,我得到大小为 2352 的扇区,每个扇区的实际模式 1 数据之前有 16 个字节 header。

即使使用 hexdump 等 BSD 工具,在读取 Apple 制作的旧 CD 时也可以看到这一点:

$ hexdump -n 512 -C /dev/disk8
00000000  00 ff ff ff ff ff ff ff  ff ff ff 00 00 02 00 01  |................|
00000010  45 52 08 00 00 05 00 00  00 01 00 01 00 00 00 00  |ER..............|
00000020  00 04 00 00 00 10 00 05  00 01 00 00 00 1e 00 19  |................|
00000030  ff ff 00 00 00 41 00 05  07 01 00 00 00 4f 00 1f  |.....A.......O..|
00000040  f8 ff 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

实际扇区的数据从偏移量 0x10 开始,"ER"。但是 "ER" 应该在偏移量 0.

如何才能在我自己的应用程序中完成这项工作,而不必在单独的步骤中删除额外的数据?

我查看了 "IOCDMediaBSDClient.h" 和 "IOCDTypes.h" 中的各种 ioctl 函数,但我找不到一个让我指定我只想从中获取纯数据内容的函数扇区。

我也相信我大约 15 年前编写的现有代码当时能够按需要处理此问题,但从那时起 OS X 中发生了一些变化,破坏了我的旧代码。现在我不知道如何解决这个问题。该代码使用 ioctlDKIOCCDREAD,以及参数 sectorArea=kCDSectorAreaUsersectorType=kCDSectorTypeMode1。但这给了我 16 字节的 header 就像正常的 read 调用一样,尽管 Mode1 意味着我应该得到 2048 字节的扇区而没有任何 header,据我所知它。

如评论部分所述,答案似乎是使用字符设备 (rdisk),而不是块设备 (disk) 节点。据我所知,这种区别并没有得到很好的记录,而且对于硬盘驱动器和 SSD 实际上非常小——在大多数情况下你可以使用两者之一。对于光盘,无论出于何种原因,它都有很大的不同。

我前段时间研究过这个,但不幸的是我忘记了细节。如果您对此感兴趣,可以在 Apple 的 https://opensource.apple.com/ 站点上的 "IOStorageFamily" 和 "IOCDStorageFamily" 源代码包中找到实现。

您要查找的代码文件与 "BSD clients" - IOStorageFamily 中的 IOMediaBSDClient.cpp/.h 相关,特别是与 CD 相关的 IOMediaBSDClient.cpp/.h。块 ("disk") 设备的 ioctls 首先在 dkioctl_bdev() 中处理,然后转发到通用 dkioctl(),后者又调用 IOCDMediaBSDClient::ioctl() 方法。字符设备("rdisk")使用dkioctl_cdev()代替。