mirror of
https://github.com/utmapp/UTM.git
synced 2026-10-11 21:59:56 +00:00
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
92 lines
3.8 KiB
Swift
92 lines
3.8 KiB
Swift
//
|
|
// Copyright © 2025 naveenrajm7. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
@objc extension UTMScriptingVirtualMachineImpl {
|
|
@objc var registry: [URL] {
|
|
let wrapper = UTMScriptingRegistryEntryImpl(vm.registryEntry)
|
|
return wrapper.serializeRegistry()
|
|
}
|
|
|
|
@objc func updateRegistry(_ command: NSScriptCommand) {
|
|
let newRegistry = command.evaluatedArguments?["newRegistry"] as? [URL]
|
|
withScriptCommand(command) { [self] in
|
|
guard let newRegistry = newRegistry else {
|
|
throw ScriptingError.invalidParameter
|
|
}
|
|
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()
|
|
}
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
class UTMScriptingRegistryEntryImpl {
|
|
private(set) var registry: UTMRegistryEntry
|
|
|
|
init(_ registry: UTMRegistryEntry) {
|
|
self.registry = registry
|
|
}
|
|
|
|
func serializeRegistry() -> [URL] {
|
|
return registry.sharedDirectories.compactMap { $0.url }
|
|
}
|
|
|
|
func updateRegistry(from fileUrls: [URL], _ system: UTMQemuSystem?) async throws {
|
|
// Clear all shared directories, we add all directories here
|
|
registry.removeAllSharedDirectories()
|
|
|
|
// Add urls to the registry
|
|
for url in fileUrls {
|
|
// Start scoped access
|
|
let isScopedAccess = url.startAccessingSecurityScopedResource()
|
|
defer {
|
|
if isScopedAccess {
|
|
url.stopAccessingSecurityScopedResource()
|
|
}
|
|
}
|
|
|
|
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
|
|
registry.appendSharedDirectory(file)
|
|
}
|
|
|
|
}
|
|
}
|