如何从 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 中发生了一些变化,破坏了我的旧代码。现在我不知道如何解决这个问题。该代码使用 ioctl
和 DKIOCCDREAD
,以及参数 sectorArea=kCDSectorAreaUser
和 sectorType=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()
代替。
我正在尝试从 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 中发生了一些变化,破坏了我的旧代码。现在我不知道如何解决这个问题。该代码使用 ioctl
和 DKIOCCDREAD
,以及参数 sectorArea=kCDSectorAreaUser
和 sectorType=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()
代替。