Skip to content

Commit f4c01f3

Browse files
aganeatstellar
authored andcommitted
[Support] Fix 'keeping' temporary files on Windows 7
As reported here: https://bugs.llvm.org/show_bug.cgi?id=48378#c0 and here: rust-lang/rust#81051 since 79657e2, some programs such as llvm-ar don't work properly on Windows 7. The issue is shown in the snippet by Oleksandr Prodan: https://pastebin.com/v51m3uBU In essence, once the 'DeleteFile' flag has been set on FILE_DISPOSITION_INFO, the file path can't be queried anymore with GetFinalPathNameByHandleW. This however works on Windows 10, GetFinalPathNameByHandleW would return sucessfully. To workaround the issue, we simply reset the 'DeleteFile' flag before even checking if we're dealing with a network file. Tested with `llvm-ar r empty.a a.obj` ran on a network mount. At the moment, we cannot specifically add a test coverage for this, since it requres mounting a network drive. (cherry picked from commit 64ab2b6)
1 parent 4990141 commit f4c01f3

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

llvm/lib/Support/Windows/Path.inc

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,22 @@ std::error_code is_local(int FD, bool &Result) {
402402
}
403403

404404
static std::error_code setDeleteDisposition(HANDLE Handle, bool Delete) {
405-
// First, check if the file is on a network (non-local) drive. If so, don't
406-
// set DeleteFile to true, since it prevents opening the file for writes.
405+
// Clear the FILE_DISPOSITION_INFO flag first, before checking if it's a
406+
// network file. On Windows 7 the function realPathFromHandle() below fails
407+
// if the FILE_DISPOSITION_INFO flag was already set to 'DeleteFile = true' by
408+
// a prior call.
409+
FILE_DISPOSITION_INFO Disposition;
410+
Disposition.DeleteFile = false;
411+
if (!SetFileInformationByHandle(Handle, FileDispositionInfo, &Disposition,
412+
sizeof(Disposition)))
413+
return mapWindowsError(::GetLastError());
414+
if (!Delete)
415+
return std::error_code();
416+
417+
// Check if the file is on a network (non-local) drive. If so, don't
418+
// continue when DeleteFile is true, since it prevents opening the file for
419+
// writes. Note -- this will leak temporary files on disk, but only when the
420+
// target file is on a network drive.
407421
SmallVector<wchar_t, 128> FinalPath;
408422
if (std::error_code EC = realPathFromHandle(Handle, FinalPath))
409423
return EC;
@@ -415,9 +429,9 @@ static std::error_code setDeleteDisposition(HANDLE Handle, bool Delete) {
415429
if (!IsLocal)
416430
return std::error_code();
417431

418-
// The file is on a local drive, set the DeleteFile to true.
419-
FILE_DISPOSITION_INFO Disposition;
420-
Disposition.DeleteFile = Delete;
432+
// The file is on a local drive, we can safely set FILE_DISPOSITION_INFO's
433+
// flag.
434+
Disposition.DeleteFile = true;
421435
if (!SetFileInformationByHandle(Handle, FileDispositionInfo, &Disposition,
422436
sizeof(Disposition)))
423437
return mapWindowsError(::GetLastError());

0 commit comments

Comments
 (0)