Пронумеруйте приводы оптических дисков в C, как это делает drutil для командной строки OS X

Имена устройств оптических дисков (пример: /dev/disk4) немного странные в Mac OS X. В отличие от других ОС, они принадлежат смонтированному носителю, а не дисководу, поэтому существуют только тогда, когда диск вставлен. Кроме того, они недолговечны. Они могут измениться уже при монтировании другого файла .dmg до того, как следующий диск будет вставлен в дисковод. В Windows буквы дисков стабильны, а в Linux есть имена устройств, такие как /dev/cdrom или /dev/sr0, которые довольно стабильны. Изменения в жестких дисках, USB-накопителях и пакетах не влияют на имена оптических устройств.

Я разрабатываю библиотеку C, работающую с аудио компакт-дисками, и хочу использовать нумерацию дисков, предоставленную drutil из C. drutil list перечисляет все диски, подключенные к машине (с дисками или без них, и дает им номера. С помощью drutil details -drive 1 я могу затем получить сведения о первом диске, включая имя устройства (BSD), когда диск находится в приводе.Это было бы идеально, чтобы установить предпочтительный привод в конфигурации или аналогичном.

В C я не мог перечислить или проиндексировать диски без дисков. Поэтому, когда я получаю первый вставленный диск, я не знаю, какому приводу принадлежит этот диск. Я могу получить имена устройств для вставленных дисков с расширением IOCDMediaClass. Я получаю один диск, указанный с IOCDBlockStorageDeviceClass (с вставленным диском или без него), но я не могу получить доступ к имени устройства, даже когда диск находится в дисководе.

Я подготовил пример кода, который пытается перечислить элементы обоих классов и имя устройства, если оно доступно. .

Выход без диска в приводе:

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

Выход с диском в приводе:

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

PS: я знаю, что могу вызвать drutil из C, но это будет крайняя мера.


person JonnyJD    schedule 29.07.2013    source источник
comment
Apple предоставляет общий пример кода: developer.apple .com/library/mac/#samplecode/CDROMSample/. Там дополнительно фильтруют по ejectableMedia. Это не имеет значения для моих тестов.   -  person JonnyJD    schedule 29.07.2013


Ответы (1)


Я нашел информацию, прикрепленную к IODVDServices, используя ioreg -r -c IODVDServices (ioreg). У соответствующей записи реестра есть (внучатые) дочерние элементы, один из которых имеет тип IODVDMedia, когда в приводе нет компакт-диска, и тип IOCDMedia, когда в приводе находится аудиодиск (включая имя устройства, когда диск вставлен).

Доступ к этим дочерним элементам можно получить с помощью IORegistryEntryCreateIterator() и протестирован на принадлежность к определенному классу с помощью 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;
}

Я отправил полное решение в суть.

Это пытается найти подключенный носитель, подключенный к определенному диску IOCDBlockStorageDeviceClass. Поиск имени устройства этого носителя работает так же, как указано в вопросе и CDROMSample предоставлен Apple.


РЕДАКТИРОВАТЬ:

Вы также можете просто взять любое имя BSD в одном из (рекурсивных) дочерних элементов с помощью IORegistryEntrySearchCFProperty. Не должно быть других дочерних элементов с именами устройств, и это избавляет вас от дополнительной итерации.

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

Это используется в реализации для libdiscid.

person JonnyJD    schedule 31.07.2013