mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
Merge pull request #15501 from matu3ba/win_rmwithposix
std.windows: use posix semantics to delete files, if available
This commit is contained in:
commit
e3736baddb
@ -1416,23 +1416,42 @@ test "File.PermissionsUnix" {
|
||||
try testing.expect(!permissions_unix.unixHas(.other, .execute));
|
||||
}
|
||||
|
||||
test "delete a read-only file on windows" {
|
||||
if (builtin.os.tag != .windows) return error.SkipZigTest;
|
||||
test "delete a read-only file on windows with file pending semantics" {
|
||||
if (builtin.os.tag != .windows or builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1))
|
||||
return error.SkipZigTest;
|
||||
|
||||
var tmp = tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
{
|
||||
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
||||
defer file.close();
|
||||
// Create a file and make it read-only
|
||||
const metadata = try file.metadata();
|
||||
var permissions = metadata.permissions();
|
||||
permissions.setReadOnly(true);
|
||||
try file.setPermissions(permissions);
|
||||
try testing.expectError(error.AccessDenied, tmp.dir.deleteFile("test_file"));
|
||||
// Now make the file not read-only
|
||||
permissions.setReadOnly(false);
|
||||
try file.setPermissions(permissions);
|
||||
}
|
||||
try tmp.dir.deleteFile("test_file");
|
||||
}
|
||||
|
||||
test "delete a read-only file on windows with posix semantis" {
|
||||
if (builtin.os.tag != .windows or !builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1))
|
||||
return error.SkipZigTest;
|
||||
|
||||
var tmp = tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
||||
defer file.close();
|
||||
// Create a file and make it read-only
|
||||
const metadata = try file.metadata();
|
||||
var permissions = metadata.permissions();
|
||||
permissions.setReadOnly(true);
|
||||
try file.setPermissions(permissions);
|
||||
try testing.expectError(error.AccessDenied, tmp.dir.deleteFile("test_file"));
|
||||
// Now make the file not read-only
|
||||
permissions.setReadOnly(false);
|
||||
try file.setPermissions(permissions);
|
||||
file.close();
|
||||
try tmp.dir.deleteFile("test_file");
|
||||
try tmp.dir.deleteFile("test_file"); // file is unmapped and deleted once last handle closed
|
||||
}
|
||||
|
||||
test "delete a setAsCwd directory on Windows" {
|
||||
|
||||
@ -937,19 +937,40 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
|
||||
.DELETE_PENDING => return,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
var file_dispo = FILE_DISPOSITION_INFORMATION{
|
||||
.DeleteFile = TRUE,
|
||||
};
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
tmp_handle,
|
||||
&io,
|
||||
&file_dispo,
|
||||
@sizeOf(FILE_DISPOSITION_INFORMATION),
|
||||
.FileDispositionInformation,
|
||||
);
|
||||
CloseHandle(tmp_handle);
|
||||
defer CloseHandle(tmp_handle);
|
||||
|
||||
if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
|
||||
// Deletion with posix semantics.
|
||||
var info = FILE_DISPOSITION_INFORMATION_EX{
|
||||
.Flags = FILE_DISPOSITION_DELETE |
|
||||
FILE_DISPOSITION_POSIX_SEMANTICS |
|
||||
FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE,
|
||||
};
|
||||
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
tmp_handle,
|
||||
&io,
|
||||
&info,
|
||||
@sizeOf(FILE_DISPOSITION_INFORMATION_EX),
|
||||
.FileDispositionInformationEx,
|
||||
);
|
||||
} else {
|
||||
// Deletion with file pending semantics, which requires waiting or moving
|
||||
// files to get them removed (from here).
|
||||
var file_dispo = FILE_DISPOSITION_INFORMATION{
|
||||
.DeleteFile = TRUE,
|
||||
};
|
||||
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
tmp_handle,
|
||||
&io,
|
||||
&file_dispo,
|
||||
@sizeOf(FILE_DISPOSITION_INFORMATION),
|
||||
.FileDispositionInformation,
|
||||
);
|
||||
}
|
||||
switch (rc) {
|
||||
.SUCCESS => return,
|
||||
.SUCCESS => {},
|
||||
.DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
.CANNOT_DELETE => return error.AccessDenied,
|
||||
@ -2574,6 +2595,18 @@ pub const FILE_NAME_INFORMATION = extern struct {
|
||||
FileName: [1]WCHAR,
|
||||
};
|
||||
|
||||
pub const FILE_DISPOSITION_INFORMATION_EX = extern struct {
|
||||
/// combination of FILE_DISPOSITION_* flags
|
||||
Flags: ULONG,
|
||||
};
|
||||
|
||||
const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000;
|
||||
const FILE_DISPOSITION_DELETE: ULONG = 0x00000001;
|
||||
const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002;
|
||||
const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004;
|
||||
const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008;
|
||||
const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010;
|
||||
|
||||
pub const FILE_RENAME_INFORMATION = extern struct {
|
||||
ReplaceIfExists: BOOLEAN,
|
||||
RootDirectory: ?HANDLE,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user