fix(macos): keep optical drive identity stable during exclusive access

This commit is contained in:
Matthew Jackson
2026-10-05 13:04:40 -07:00
parent 92847607b9
commit a69a8d9bbd
3 changed files with 13 additions and 9 deletions
+4
View File
@@ -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
+6 -6
View File
@@ -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, &registry_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))) {
// 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;
}
+2 -2
View File
@@ -561,8 +561,8 @@ pub(crate) fn open_with(device: &Path, halt: &crate::halt::Halt) -> Result<Box<d
/// no firmware reset, no init.
#[derive(Debug, Clone)]
pub struct DriveInfo {
/// Platform device path: `/dev/sgN` (Linux), `/dev/diskN` or an opaque
/// `ioreg:<id>` selector for an empty optical drive (macOS), `\\.\CdRomN`
/// Platform device path: `/dev/sgN` (Linux), a stable optical-service
/// `ioreg:<id>` selector (macOS), `\\.\CdRomN`
/// (Windows).
pub path: String,
/// SCSI INQUIRY vendor identifier (e.g. `"HL-DT-ST"`).