authorgravatar for spexguy070@gmail.comMartin Wickham <spexguy070@gmail.com> 2022-06-04 17:34:21-05:00
committergravatar for jan.hafer@rwth-aachen.deJan Philipp Hafer <jan.hafer@rwth-aachen.de> 2023-05-01 15:46:58+02:00
log0f0f005e927be5e9d813e40c8c6c6580fd4f5697
tree5152fa20a8da97f29c0a3e73a4802f5ac53c19cd
parente963793e37f93d84f1e5295d309ebe0c738b663d

std.windows: use posix semantics to delete files, if available

Justification: When a file is deleted on Windows, it may not be immediately removed from the directory. This can cause problems with future scans of that directory, which will see the partially deleted file. Under some workloads and system configurations, Windows files may appear to be deleted immediately. This is the PR with requested fixup. Thanks to @SpexGuy for the original PR.

1 files changed, 56 insertions(+), 19 deletions(-)

lib/std/os/windows.zig+56-19
...@@ -937,25 +937,50 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil...@@ -937,25 +937,50 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
937 .DELETE_PENDING => return,937 .DELETE_PENDING => return,
938 else => return unexpectedStatus(rc),938 else => return unexpectedStatus(rc),
939 }939 }
940 var file_dispo = FILE_DISPOSITION_INFORMATION{940 defer CloseHandle(tmp_handle);
941 .DeleteFile = TRUE,941 if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
942 };942 // Deletion with posix semantics.
943 rc = ntdll.NtSetInformationFile(943 var info = FILE_DISPOSITION_INFORMATION_EX{
944 tmp_handle,944 .Flags = FILE_DISPOSITION_DELETE |
945 &io,945 FILE_DISPOSITION_POSIX_SEMANTICS |
946 &file_dispo,946 FILE_DISPOSITION_ON_CLOSE |
947 @sizeOf(FILE_DISPOSITION_INFORMATION),947 FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE,
948 .FileDispositionInformation,948 };
949 );949
950 CloseHandle(tmp_handle);950 rc = ntdll.NtSetInformationFile(
951 switch (rc) {951 tmp_handle,
952 .SUCCESS => return,952 &io,
953 .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,953 &info,
954 .INVALID_PARAMETER => unreachable,954 @sizeOf(FILE_DISPOSITION_INFORMATION_EX),
955 .CANNOT_DELETE => return error.AccessDenied,955 .FileDispositionInformationEx,
956 .MEDIA_WRITE_PROTECTED => return error.AccessDenied,956 );
957 .ACCESS_DENIED => return error.AccessDenied,957 switch (rc) {
958 else => return unexpectedStatus(rc),958 .SUCCESS => {},
959 .CANNOT_DELETE => return error.FileBusy, // file is currently mapped
960 else => return unexpectedStatus(rc),
961 }
962 } else {
963 // Deletion with file pending semantics, which requires waiting or moving
964 // files to get them removed (from here).
965 var file_dispo = FILE_DISPOSITION_INFORMATION{
966 .DeleteFile = TRUE,
967 };
968 rc = ntdll.NtSetInformationFile(
969 tmp_handle,
970 &io,
971 &file_dispo,
972 @sizeOf(FILE_DISPOSITION_INFORMATION),
973 .FileDispositionInformation,
974 );
975 switch (rc) {
976 .SUCCESS => {},
977 .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,
978 .INVALID_PARAMETER => unreachable,
979 .CANNOT_DELETE => return error.AccessDenied,
980 .MEDIA_WRITE_PROTECTED => return error.AccessDenied,
981 .ACCESS_DENIED => return error.AccessDenied,
982 else => return unexpectedStatus(rc),
983 }
959 }984 }
960}985}
961986
...@@ -2397,6 +2422,18 @@ pub const FILE_NAME_INFORMATION = extern struct {...@@ -2397,6 +2422,18 @@ pub const FILE_NAME_INFORMATION = extern struct {
2397 FileName: [1]WCHAR,2422 FileName: [1]WCHAR,
2398};2423};
23992424
2425pub const FILE_DISPOSITION_INFORMATION_EX = extern struct {
2426 /// combination of FILE_DISPOSITION_* flags
2427 Flags: ULONG,
2428};
2429
2430const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000;
2431const FILE_DISPOSITION_DELETE: ULONG = 0x00000001;
2432const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002;
2433const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004;
2434const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008;
2435const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010;
2436
2400pub const FILE_RENAME_INFORMATION = extern struct {2437pub const FILE_RENAME_INFORMATION = extern struct {
2401 ReplaceIfExists: BOOLEAN,2438 ReplaceIfExists: BOOLEAN,
2402 RootDirectory: ?HANDLE,2439 RootDirectory: ?HANDLE,