authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-07-22 23:27:11-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-07-23 01:26:26-07:00
log1ae378e7a253ec845d8ee8d52b5505c9aa177369
tree9870995f852bef3b240fd3375edfdecdba1eb855
parent1bf16b1723445ba307ca556dc050d6d13bb0ebff

windows.DeleteFile: Use FileDispositionInformationEx if possible, but fallback if not

Using FileDispositionInformationEx (and therefore flags like FILE_DISPOSITION_POSIX_SEMANTICS and FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE) is only supported on NTFS, so the comptime Windows version range check is not enough to determine whether or not the NtSetInformationFile will succeed. This commit makes DeleteFile always try using FileDispositionInformationEx first, but if INVALID_PARAMETER is received (which is the status that occurs when the filesystem doesn't support FileDispositionInformationEx), then it will fallback and try calling NtSetInformationFile with FileDispositionInformation. This keeps NTFS as fast as it was before, since it will do at most 1 NtSetInformationFile call, but on non-NTFS filesystems (e.g. FAT32), DeleteFile may need to do 2 NtSetInformationFile calls. Closes #16497

1 files changed, 14 insertions(+), 2 deletions(-)

lib/std/os/windows.zig+14-2
......@@ -940,8 +940,13 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
940940 }
941941 defer CloseHandle(tmp_handle);
942942
943 // FileDispositionInformationEx (and therefore FILE_DISPOSITION_POSIX_SEMANTICS and FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE)
944 // are only supported on NTFS filesystems, so the version check on its own is only a partial solution. To support non-NTFS filesystems
945 // like FAT32, we need to fallback to FileDispositionInformation if the usage of FileDispositionInformationEx gives
946 // us INVALID_PARAMETER.
947 var need_fallback = true;
943948 if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
944 // Deletion with posix semantics.
949 // Deletion with posix semantics if the filesystem supports it.
945950 var info = FILE_DISPOSITION_INFORMATION_EX{
946951 .Flags = FILE_DISPOSITION_DELETE |
947952 FILE_DISPOSITION_POSIX_SEMANTICS |
......@@ -955,7 +960,14 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
955960 @sizeOf(FILE_DISPOSITION_INFORMATION_EX),
956961 .FileDispositionInformationEx,
957962 );
958 } else {
963 switch (rc) {
964 // INVALID_PARAMETER here means that the filesystem does not support FileDispositionInformationEx
965 .INVALID_PARAMETER => {},
966 // For all other statuses, fall down to the switch below to handle them.
967 else => need_fallback = false,
968 }
969 }
970 if (need_fallback) {
959971 // Deletion with file pending semantics, which requires waiting or moving
960972 // files to get them removed (from here).
961973 var file_dispo = FILE_DISPOSITION_INFORMATION{