mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #16499 from squeek502/posix-semantics-2
windows.DeleteFile: Use FileDispositionInformationEx if possible, but fallback if not
This commit is contained in:
commit
b35874a429
@ -1416,13 +1416,13 @@ test "File.PermissionsUnix" {
|
|||||||
try testing.expect(!permissions_unix.unixHas(.other, .execute));
|
try testing.expect(!permissions_unix.unixHas(.other, .execute));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "delete a read-only file on windows with file pending semantics" {
|
test "delete a read-only file on windows" {
|
||||||
if (builtin.os.tag != .windows or builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1))
|
if (builtin.os.tag != .windows)
|
||||||
return error.SkipZigTest;
|
return error.SkipZigTest;
|
||||||
|
|
||||||
var tmp = tmpDir(.{});
|
var tmp = testing.tmpDir(.{});
|
||||||
defer tmp.cleanup();
|
defer tmp.cleanup();
|
||||||
{
|
|
||||||
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
||||||
defer file.close();
|
defer file.close();
|
||||||
// Create a file and make it read-only
|
// Create a file and make it read-only
|
||||||
@ -1430,28 +1430,21 @@ test "delete a read-only file on windows with file pending semantics" {
|
|||||||
var permissions = metadata.permissions();
|
var permissions = metadata.permissions();
|
||||||
permissions.setReadOnly(true);
|
permissions.setReadOnly(true);
|
||||||
try file.setPermissions(permissions);
|
try file.setPermissions(permissions);
|
||||||
try testing.expectError(error.AccessDenied, tmp.dir.deleteFile("test_file"));
|
|
||||||
|
// If the OS and filesystem support it, POSIX_SEMANTICS and IGNORE_READONLY_ATTRIBUTE
|
||||||
|
// is used meaning that the deletion of a read-only file will succeed.
|
||||||
|
// Otherwise, this delete will fail and the read-only flag must be unset before it's
|
||||||
|
// able to be deleted.
|
||||||
|
const delete_result = tmp.dir.deleteFile("test_file");
|
||||||
|
if (delete_result) {
|
||||||
|
try testing.expectError(error.FileNotFound, tmp.dir.deleteFile("test_file"));
|
||||||
|
} else |err| {
|
||||||
|
try testing.expectEqual(@as(anyerror, error.AccessDenied), err);
|
||||||
// Now make the file not read-only
|
// Now make the file not read-only
|
||||||
permissions.setReadOnly(false);
|
permissions.setReadOnly(false);
|
||||||
try file.setPermissions(permissions);
|
try file.setPermissions(permissions);
|
||||||
}
|
|
||||||
try tmp.dir.deleteFile("test_file");
|
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 tmp.dir.deleteFile("test_file"); // file is unmapped and deleted once last handle closed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "delete a setAsCwd directory on Windows" {
|
test "delete a setAsCwd directory on Windows" {
|
||||||
|
|||||||
@ -940,8 +940,13 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
|
|||||||
}
|
}
|
||||||
defer CloseHandle(tmp_handle);
|
defer CloseHandle(tmp_handle);
|
||||||
|
|
||||||
|
// FileDispositionInformationEx (and therefore FILE_DISPOSITION_POSIX_SEMANTICS and FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE)
|
||||||
|
// are only supported on NTFS filesystems, so the version check on its own is only a partial solution. To support non-NTFS filesystems
|
||||||
|
// like FAT32, we need to fallback to FileDispositionInformation if the usage of FileDispositionInformationEx gives
|
||||||
|
// us INVALID_PARAMETER.
|
||||||
|
var need_fallback = true;
|
||||||
if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
|
if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
|
||||||
// Deletion with posix semantics.
|
// Deletion with posix semantics if the filesystem supports it.
|
||||||
var info = FILE_DISPOSITION_INFORMATION_EX{
|
var info = FILE_DISPOSITION_INFORMATION_EX{
|
||||||
.Flags = FILE_DISPOSITION_DELETE |
|
.Flags = FILE_DISPOSITION_DELETE |
|
||||||
FILE_DISPOSITION_POSIX_SEMANTICS |
|
FILE_DISPOSITION_POSIX_SEMANTICS |
|
||||||
@ -955,7 +960,14 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
|
|||||||
@sizeOf(FILE_DISPOSITION_INFORMATION_EX),
|
@sizeOf(FILE_DISPOSITION_INFORMATION_EX),
|
||||||
.FileDispositionInformationEx,
|
.FileDispositionInformationEx,
|
||||||
);
|
);
|
||||||
} else {
|
switch (rc) {
|
||||||
|
// INVALID_PARAMETER here means that the filesystem does not support FileDispositionInformationEx
|
||||||
|
.INVALID_PARAMETER => {},
|
||||||
|
// For all other statuses, fall down to the switch below to handle them.
|
||||||
|
else => need_fallback = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (need_fallback) {
|
||||||
// Deletion with file pending semantics, which requires waiting or moving
|
// Deletion with file pending semantics, which requires waiting or moving
|
||||||
// files to get them removed (from here).
|
// files to get them removed (from here).
|
||||||
var file_dispo = FILE_DISPOSITION_INFORMATION{
|
var file_dispo = FILE_DISPOSITION_INFORMATION{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user