From a69a8d9bbda0fb76d9ea64e483ac0ee6278df78b Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Mon, 5 Oct 2026 13:04:40 -0700 Subject: [PATCH] fix(macos): keep optical drive identity stable during exclusive access --- CHANGELOG.md | 4 ++++ src/scsi/macos_shim.c | 14 +++++++------- src/scsi/mod.rs | 4 ++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16fe9882..074cfb58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- macOS optical-drive enumeration keeps the same IOKit service selector with or without mounted media, so exclusive access during a rip does not turn one drive into two identities. + ## [1.8.0] — 2026-10-05 ### Breaking diff --git a/src/scsi/macos_shim.c b/src/scsi/macos_shim.c index f19daa3f..8810f853 100644 --- a/src/scsi/macos_shim.c +++ b/src/scsi/macos_shim.c @@ -179,10 +179,9 @@ static int registry_entry_bsd_name(io_registry_entry_t entry, char *buf, size_t return ok; } -// Empty optical drives have a service node but no IOMedia node, hence -// no BSD diskN name. Use the service's IOKit registry ID as an opaque selector -// until media appears. It is process/boot-local, which is sufficient for the -// list-then-open GUI flow. +// Optical services outlive their IOMedia nodes, which disappear for an empty +// tray and during exclusive access. Use the service registry ID as the stable +// selector throughout insertion, ripping and ejection (until unplug/reboot). static int registry_id_selector(io_registry_entry_t entry, char *buf, size_t buflen) { uint64_t registry_id = 0; if (IORegistryEntryGetRegistryEntryID(entry, ®istry_id) != KERN_SUCCESS) return 0; @@ -864,9 +863,10 @@ static int visit_list(io_service_t svc, void *ctx) { memset(info, 0, sizeof(*info)); bdsvc_device_info(svc, info); - if (!bdsvc_to_bsd_name(svc, info->device_selector, sizeof(info->device_selector))) { - registry_id_selector(svc, info->device_selector, sizeof(info->device_selector)); - } + // IOMedia (and its diskN name) disappears during exclusive access. The + // optical service survives: always use its ID so a busy drive cannot be + // enumerated as a second, apparently empty drive after opening it. + registry_id_selector(svc, info->device_selector, sizeof(info->device_selector)); if (info->device_selector[0]) lc->count++; return lc->count >= lc->max ? 2 : 0; } diff --git a/src/scsi/mod.rs b/src/scsi/mod.rs index 8189c361..235a9459 100644 --- a/src/scsi/mod.rs +++ b/src/scsi/mod.rs @@ -561,8 +561,8 @@ pub(crate) fn open_with(device: &Path, halt: &crate::halt::Halt) -> Result` selector for an empty optical drive (macOS), `\\.\CdRomN` + /// Platform device path: `/dev/sgN` (Linux), a stable optical-service + /// `ioreg:` selector (macOS), `\\.\CdRomN` /// (Windows). pub path: String, /// SCSI INQUIRY vendor identifier (e.g. `"HL-DT-ST"`).