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

222 Views Asked by At

I am trying to read the plain 2048 byte sized data sectors from a data CD on OS X.

But when I open a device such as "/dev/disk8", I get sectors of 2352 in size, with a 16 byte header before each sector's actual Mode1 data.

Even with the BSD tools such as hexdump this can be seen, when reading an older CD made by Apple:

$ 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  |................|

The actual sector's data starts here at offset 0x10 with "ER". But the "ER" should be at offset 0.

How can I make this work in my own application without having to remove the extra data in a separate step?

I looked at the various ioctl functions in "IOCDMediaBSDClient.h" and "IOCDTypes.h", but I could not find one that lets me specify that I want to get only the plain data content from the sectors.

I also believe that my existing code which I wrote about 15 years ago, was able to handle this as desired back then, but something has changed in OS X since then, breaking my old code. And now I cannot figure out how to fix that. That code uses ioctl with DKIOCCDREAD, with parameters sectorArea=kCDSectorAreaUser and sectorType=kCDSectorTypeMode1. But that gives me the 16 byte header just like a normal read call does, even though Mode1 means that I should be getting 2048 byte sectors without any headers, as far as I understand it.

1

There are 1 best solutions below

2
On BEST ANSWER

As established in the comments section, the answer seems to be to to use the character device (rdisk), not the block device (disk) node. The distinction is not well documented as far as I'm aware, and for hard drives and SSDs is actually quite small - in most cases you can use either. For optical discs it's significantly different, for whatever reason.

I looked into this some time ago, but I forget the details of it, unfortunately. If you're interested in this, you'll find the implementation in the "IOStorageFamily" and "IOCDStorageFamily" source code bundles on Apple's https://opensource.apple.com/ site.

The code files you're after are the ones relating to "BSD clients" - IOMediaBSDClient.cpp/.h in IOStorageFamily, and IOMediaBSDClient.cpp/.h for CDs specifically. The block ("disk") device's ioctls are first handled in dkioctl_bdev() and then forwarded on to the generic dkioctl(), which in turn calls the IOCDMediaBSDClient::ioctl() method. The character device ("rdisk") uses dkioctl_cdev() instead.