scripting: fix shared directory access for Apple Virtualization VMs

update registry falls back to a disconnected UTMProcess for non-QEMU
backends, which mints a non-security-scoped bookmark wrapped in an
unresolved URL; the resulting entry can never be accessed, so the VM
fails to start with "Cannot access resource". Build a real
security-scoped bookmark directly for the Apple backend instead, and
explicitly resync config from the registry since there is no QEMU
process to trigger it.

Assisted-by: Claude:claude-sonnet-5
This commit is contained in:
Sam Atkinson
2026-08-25 15:12:54 -04:00
parent 8e4de50817
commit f2c3ecaedc
+22 -8
View File
@@ -30,6 +30,10 @@ import Foundation
}
let wrapper = UTMScriptingRegistryEntryImpl(vm.registryEntry)
try await wrapper.updateRegistry(from: newRegistry, qemuProcess)
// For Apple Virtualization VMs there is no QEMU process to notify, and the
// registry -> config sync otherwise only happens incidentally via VMData's
// Combine subscription, so do it explicitly here.
await (vm as? UTMAppleVirtualMachine)?.updateConfigFromRegistry()
}
}
}
@@ -60,16 +64,26 @@ class UTMScriptingRegistryEntryImpl {
}
}
// Get bookmark from UTM process
let standardBookmark = try url.bookmarkData()
let system = system ?? UTMProcess()
let (success, bookmark, path) = await system.accessData(withBookmark: standardBookmark, securityScoped: false)
guard let bookmark = bookmark, let _ = path, success else {
throw UTMQemuVirtualMachineError.accessDriveImageFailed
let file: UTMRegistryEntry.File
if let system = system {
// QEMU backend: hand the standard bookmark off to the XPC helper so it
// mints its own security-scoped bookmark valid within its own sandbox.
let standardBookmark = try url.bookmarkData()
let (success, bookmark, path) = await system.accessData(withBookmark: standardBookmark, securityScoped: false)
guard let bookmark = bookmark, let _ = path, success else {
throw UTMQemuVirtualMachineError.accessDriveImageFailed
}
file = UTMRegistryEntry.File(dummyFromPath: url.path, remoteBookmark: bookmark)
} else {
// Apple Virtualization backend: QEMU runs in-process, so create a real
// security-scoped bookmark directly (no XPC helper to hand it off to),
// then resolve it back into a URL that actually carries the security
// scope, the same way the registry does when reloading from disk.
let bookmark = try url.persistentBookmarkData(isReadyOnly: false)
file = try UTMRegistryEntry.File(path: url.path, bookmark: bookmark)
}
// Store bookmark in registry
let file = UTMRegistryEntry.File(dummyFromPath: url.path, remoteBookmark: bookmark)
registry.appendSharedDirectory(file)
}