From 0b72dd467446346af0303e3fff2d48d078009d56 Mon Sep 17 00:00:00 2001 From: James Stringer <38541878+jamesstringer90@users.noreply.github.com> Date: Mon, 21 Sep 2026 18:14:09 -0400 Subject: [PATCH] Allow deleting VMs whose folders are already missing Remove the saved VM entry on Windows and macOS when its folder has already been deleted. Preserve errors for inaccessible storage and other deletion failures. Verified through the Windows headless API: the previous build fails with 0x80070002; the rebuilt app removes the VM from the list and vms.cfg. macOS code reviewed; not runtime-tested. Fixes #146. --- src/backend_mac/vm_dir.m | 7 ++++++- src/backend_win/asb_core.c | 26 ++++++++++++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/backend_mac/vm_dir.m b/src/backend_mac/vm_dir.m index 242feb0..644a127 100644 --- a/src/backend_mac/vm_dir.m +++ b/src/backend_mac/vm_dir.m @@ -145,7 +145,12 @@ /* Leave unrelated files in the VM's disk directory. */ rmdir(diskDir.fileSystemRepresentation); } - return [[NSFileManager defaultManager] removeItemAtURL:dir error:error]; + NSError *removeError = nil; + if ([[NSFileManager defaultManager] removeItemAtURL:dir error:&removeError]) return YES; + if ([removeError.domain isEqualToString:NSCocoaErrorDomain] && + removeError.code == NSFileNoSuchFileError) return YES; + if (error) *error = removeError; + return NO; } @end diff --git a/src/backend_win/asb_core.c b/src/backend_win/asb_core.c index ac98a42..fbd18fd 100644 --- a/src/backend_win/asb_core.c +++ b/src/backend_win/asb_core.c @@ -3847,11 +3847,25 @@ ASB_API HRESULT asb_vm_delete(AsbVm vm) if (!get_vm_disk_root(inst->vhdx_path, dir)) return E_INVALIDARG; attrs = GetFileAttributesW(dir); if (attrs == INVALID_FILE_ATTRIBUTES) { - hr = HRESULT_FROM_WIN32(GetLastError()); - asb_log(L"Error: VM disk folder is unavailable: %s (0x%08X).", dir, hr); - return hr; - } - if (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) return HRESULT_FROM_WIN32(ERROR_DIRECTORY); + DWORD err = GetLastError(); + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) { + wchar_t parent[MAX_PATH]; + DWORD parent_attrs; + asb_vm_disk_directory(vm, parent, MAX_PATH); + parent_attrs = GetFileAttributesW(parent); + if (parent_attrs == INVALID_FILE_ATTRIBUTES) + err = GetLastError(); + else if (!(parent_attrs & FILE_ATTRIBUTE_DIRECTORY)) + err = ERROR_DIRECTORY; + else + err = ERROR_SUCCESS; + } + if (err != ERROR_SUCCESS) { + hr = HRESULT_FROM_WIN32(err); + asb_log(L"Error: VM disk folder is unavailable: %s (0x%08X).", dir, hr); + return hr; + } + } else if (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) return HRESULT_FROM_WIN32(ERROR_DIRECTORY); hcs_stop_monitor(inst); vm_ssh_proxy_stop(inst); @@ -3869,7 +3883,7 @@ ASB_API HRESULT asb_vm_delete(AsbVm vm) /* Recursively remove the whole VM folder, including subdirectories (snapshots\ and the build's _vhdx_staging\); a file-only delete would leave those and orphan the dir. */ - if (!remove_dir_recursive(dir)) { + if (attrs != INVALID_FILE_ATTRIBUTES && !remove_dir_recursive(dir)) { hr = HRESULT_FROM_WIN32(GetLastError()); asb_log(L"Error: Cannot remove VM disk folder: %s (0x%08X).", dir, hr); save_vm_list();