Skip to content

Commit 0f0f005

Browse files
SpexGuyJan Philipp Hafer
authored and
Jan Philipp Hafer
committed
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 parent e963793 commit 0f0f005

File tree

1 file changed

+56
-19
lines changed

1 file changed

+56
-19
lines changed

lib/std/os/windows.zig

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -937,25 +937,50 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
937937
.DELETE_PENDING => return,
938938
else => return unexpectedStatus(rc),
939939
}
940-
var file_dispo = FILE_DISPOSITION_INFORMATION{
941-
.DeleteFile = TRUE,
942-
};
943-
rc = ntdll.NtSetInformationFile(
944-
tmp_handle,
945-
&io,
946-
&file_dispo,
947-
@sizeOf(FILE_DISPOSITION_INFORMATION),
948-
.FileDispositionInformation,
949-
);
950-
CloseHandle(tmp_handle);
951-
switch (rc) {
952-
.SUCCESS => return,
953-
.DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,
954-
.INVALID_PARAMETER => unreachable,
955-
.CANNOT_DELETE => return error.AccessDenied,
956-
.MEDIA_WRITE_PROTECTED => return error.AccessDenied,
957-
.ACCESS_DENIED => return error.AccessDenied,
958-
else => return unexpectedStatus(rc),
940+
defer CloseHandle(tmp_handle);
941+
if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
942+
// Deletion with posix semantics.
943+
var info = FILE_DISPOSITION_INFORMATION_EX{
944+
.Flags = FILE_DISPOSITION_DELETE |
945+
FILE_DISPOSITION_POSIX_SEMANTICS |
946+
FILE_DISPOSITION_ON_CLOSE |
947+
FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE,
948+
};
949+
950+
rc = ntdll.NtSetInformationFile(
951+
tmp_handle,
952+
&io,
953+
&info,
954+
@sizeOf(FILE_DISPOSITION_INFORMATION_EX),
955+
.FileDispositionInformationEx,
956+
);
957+
switch (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+
}
959984
}
960985
}
961986

@@ -2397,6 +2422,18 @@ pub const FILE_NAME_INFORMATION = extern struct {
23972422
FileName: [1]WCHAR,
23982423
};
23992424

2425+
pub const FILE_DISPOSITION_INFORMATION_EX = extern struct {
2426+
/// combination of FILE_DISPOSITION_* flags
2427+
Flags: ULONG,
2428+
};
2429+
2430+
const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000;
2431+
const FILE_DISPOSITION_DELETE: ULONG = 0x00000001;
2432+
const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002;
2433+
const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004;
2434+
const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008;
2435+
const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010;
2436+
24002437
pub const FILE_RENAME_INFORMATION = extern struct {
24012438
ReplaceIfExists: BOOLEAN,
24022439
RootDirectory: ?HANDLE,

0 commit comments

Comments
 (0)