authorgravatar for jan.hafer@rwth-aachen.deJan Philipp Hafer <jan.hafer@rwth-aachen.de> 2023-05-01 18:22:28+02:00
committergravatar for jan.hafer@rwth-aachen.deJan Philipp Hafer <jan.hafer@rwth-aachen.de> 2023-05-01 18:22:28+02:00
log7594d2c0977497c81db0c394f775832689bad492
treeb1088f40e4272f1da6633f9cd01b02948b3941ab
parentbe50dbf1ce03f5dc5deef86882ab3505363b683a

address review by user @squeek502


2 files changed, 38 insertions(+), 22 deletions(-)

lib/std/fs/test.zig+27-8
...@@ -1416,23 +1416,42 @@ test "File.PermissionsUnix" {...@@ -1416,23 +1416,42 @@ test "File.PermissionsUnix" {
1416 try testing.expect(!permissions_unix.unixHas(.other, .execute));1416 try testing.expect(!permissions_unix.unixHas(.other, .execute));
1417}1417}
14181418
1419test "delete a read-only file on windows" {1419test "delete a read-only file on windows with file pending semantics" {
1420 if (builtin.os.tag != .windows) return error.SkipZigTest;1420 if (builtin.os.tag != .windows or builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1))
1421 return error.SkipZigTest;
1422
1423 var tmp = tmpDir(.{});
1424 defer tmp.cleanup();
1425 {
1426 const file = try tmp.dir.createFile("test_file", .{ .read = true });
1427 defer file.close();
1428 // Create a file and make it read-only
1429 const metadata = try file.metadata();
1430 var permissions = metadata.permissions();
1431 permissions.setReadOnly(true);
1432 try file.setPermissions(permissions);
1433 try testing.expectError(error.AccessDenied, tmp.dir.deleteFile("test_file"));
1434 // Now make the file not read-only
1435 permissions.setReadOnly(false);
1436 try file.setPermissions(permissions);
1437 }
1438 try tmp.dir.deleteFile("test_file");
1439}
1440
1441test "delete a read-only file on windows with posix semantis" {
1442 if (builtin.os.tag != .windows or !builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1))
1443 return error.SkipZigTest;
14211444
1422 var tmp = tmpDir(.{});1445 var tmp = tmpDir(.{});
1423 defer tmp.cleanup();1446 defer tmp.cleanup();
1424 const file = try tmp.dir.createFile("test_file", .{ .read = true });1447 const file = try tmp.dir.createFile("test_file", .{ .read = true });
1448 defer file.close();
1425 // Create a file and make it read-only1449 // Create a file and make it read-only
1426 const metadata = try file.metadata();1450 const metadata = try file.metadata();
1427 var permissions = metadata.permissions();1451 var permissions = metadata.permissions();
1428 permissions.setReadOnly(true);1452 permissions.setReadOnly(true);
1429 try file.setPermissions(permissions);1453 try file.setPermissions(permissions);
1430 try testing.expectError(error.AccessDenied, tmp.dir.deleteFile("test_file"));1454 try tmp.dir.deleteFile("test_file"); // file is unmapped and deleted once last handle closed
1431 // Now make the file not read-only
1432 permissions.setReadOnly(false);
1433 try file.setPermissions(permissions);
1434 file.close();
1435 try tmp.dir.deleteFile("test_file");
1436}1455}
14371456
1438test "delete a setAsCwd directory on Windows" {1457test "delete a setAsCwd directory on Windows" {
lib/std/os/windows.zig+11-14
...@@ -938,6 +938,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil...@@ -938,6 +938,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
938 else => return unexpectedStatus(rc),938 else => return unexpectedStatus(rc),
939 }939 }
940 defer CloseHandle(tmp_handle);940 defer CloseHandle(tmp_handle);
941
941 if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {942 if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) {
942 // Deletion with posix semantics.943 // Deletion with posix semantics.
943 var info = FILE_DISPOSITION_INFORMATION_EX{944 var info = FILE_DISPOSITION_INFORMATION_EX{
...@@ -953,17 +954,13 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil...@@ -953,17 +954,13 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
953 @sizeOf(FILE_DISPOSITION_INFORMATION_EX),954 @sizeOf(FILE_DISPOSITION_INFORMATION_EX),
954 .FileDispositionInformationEx,955 .FileDispositionInformationEx,
955 );956 );
956 switch (rc) {
957 .SUCCESS => {},
958 .CANNOT_DELETE => return error.FileBusy, // file is currently mapped
959 else => return unexpectedStatus(rc),
960 }
961 } else {957 } else {
962 // Deletion with file pending semantics, which requires waiting or moving958 // Deletion with file pending semantics, which requires waiting or moving
963 // files to get them removed (from here).959 // files to get them removed (from here).
964 var file_dispo = FILE_DISPOSITION_INFORMATION{960 var file_dispo = FILE_DISPOSITION_INFORMATION{
965 .DeleteFile = TRUE,961 .DeleteFile = TRUE,
966 };962 };
963
967 rc = ntdll.NtSetInformationFile(964 rc = ntdll.NtSetInformationFile(
968 tmp_handle,965 tmp_handle,
969 &io,966 &io,
...@@ -971,15 +968,15 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil...@@ -971,15 +968,15 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
971 @sizeOf(FILE_DISPOSITION_INFORMATION),968 @sizeOf(FILE_DISPOSITION_INFORMATION),
972 .FileDispositionInformation,969 .FileDispositionInformation,
973 );970 );
974 switch (rc) {971 }
975 .SUCCESS => {},972 switch (rc) {
976 .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,973 .SUCCESS => {},
977 .INVALID_PARAMETER => unreachable,974 .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,
978 .CANNOT_DELETE => return error.AccessDenied,975 .INVALID_PARAMETER => unreachable,
979 .MEDIA_WRITE_PROTECTED => return error.AccessDenied,976 .CANNOT_DELETE => return error.AccessDenied,
980 .ACCESS_DENIED => return error.AccessDenied,977 .MEDIA_WRITE_PROTECTED => return error.AccessDenied,
981 else => return unexpectedStatus(rc),978 .ACCESS_DENIED => return error.AccessDenied,
982 }979 else => return unexpectedStatus(rc),
983 }980 }
984}981}
985982