Question

Optical disc device names (examle: /dev/disk4) are a bit weird on Mac OS X. Unlike on other OSs, they belong to the mounted media, not the drive so only exist when a disc is inserted. Additionally they are in no term stable. They can change already when anoter .dmg file is mounted before the next disc is inserted into the drive. On Windows drive letters are stable and linux has device names like /dev/cdrom or /dev/sr0 which are quite stable. Changes in hard discs, usb drives and packages have no effect on optical device names there.

I develop a C library working with audio CDs and would like to use the drive numbering exposed by drutil from C. drutil list lists all drives connected to the machine (with or without disc and gives them numbers. With drutil details -drive 1 I can then get the details for the first drive, including the (BSD) device name when a disc is in the drive. This would be perfect to set a prefered drive in the configuration or similar.

In C I wasn't able to list or index the drives without discs. So when I get the first inserted disc I don't know which drive this disc belongs to. I can get device names for inserted discs with the IOCDMediaClass. I do get a one drive listed with the IOCDBlockStorageDeviceClass (with or without a disc inserted), but I can't access the device name even when a disc is in the drive.

I prepared some example code that tries to list members of both classes and the device name if available.

The output without a disc in the drive:

detected media:
detected CD block devices:
drive 1:
        class name: IODVDServices

The output with a disc in the drive:

detected media:
drive 1:
        device name: disk4
        class name: IOCDMedia
detected CD block devices:
drive 1:
        class name: IODVDServices

PS: I know I can call drutil from C, but that would be a last resort.

Était-ce utile?

La solution

I found the information attached to IODVDServices using ioreg -r -c IODVDServices (ioreg). The corresponding registry entry has (grand)children of which one is of type IODVDMedia when no CD is in the drive and of type IOCDMedia when an audio disc is in the drive (including the device name when a disc is inserted).

These children can be accessed with IORegistryEntryCreateIterator() and tested for being a certain class with IOObjectConformsTo():

static io_object_t get_media(io_object_t storageDevice)
{
    io_iterator_t childrenIterator;
    io_object_t nextChild;
    io_object_t mediaObject = 0;

    IORegistryEntryCreateIterator(storageDevice,
            kIOServicePlane, kIORegistryIterateRecursively,
            &childrenIterator);
    while ((nextChild = IOIteratorNext(childrenIterator))) {
        if (IOObjectConformsTo(nextChild, kIOCDMediaClass))
            mediaObject = nextChild;
        else
            IOObjectRelease(nextChild);
    }
    IOObjectRelease(childrenIterator);
    return mediaObject;
}

I pushed a complete solution to gist.

This tries to find a mounted media attached to a specific drive of IOCDBlockStorageDeviceClass. Finding the device name of that media works the same as specified in the question and the CDROMSample provided by Apple.


EDIT:

You can also just take any BSD name in one of the (recursive) children with IORegistryEntrySearchCFProperty. There shouldn't be other children with device names and this saves you the additional iteration.

deviceFilePathAsCFString = IORegistryEntrySearchCFProperty(storageDevice,
                kIOServicePlane, CFSTR(kIOBSDNameKey),
                kCFAllocatorDefault, kIORegistryIterateRecursively);

This is used in the implementation for libdiscid.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top