mirror of
https://github.com/freemkv/libfreemkv.git
synced 2026-10-07 18:13:10 +00:00
fix(macos): keep optical drive identity stable during exclusive access
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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))) {
|
||||
// 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
@@ -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"`).
|
||||
|
||||
Reference in New Issue
Block a user