| author | |
| committer | |
| log | 7594d2c0977497c81db0c394f775832689bad492 |
| tree | b1088f40e4272f1da6633f9cd01b02948b3941ab |
| parent | be50dbf1ce03f5dc5deef86882ab3505363b683a |
2 files changed, 38 insertions(+), 22 deletions(-)
lib/std/fs/test.zig+27-8| ... | ... | @@ -1416,23 +1416,42 @@ test "File.PermissionsUnix" { |
| 1416 | 1416 | try testing.expect(!permissions_unix.unixHas(.other, .execute)); |
| 1417 | 1417 | } |
| 1418 | 1418 | |
| 1419 | test "delete a read-only file on windows" { | |
| 1420 | if (builtin.os.tag != .windows) return error.SkipZigTest; | |
| 1419 | test "delete a read-only file on windows with file pending semantics" { | |
| 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 | ||
| 1441 | test "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; | |
| 1421 | 1444 | |
| 1422 | 1445 | var tmp = tmpDir(.{}); |
| 1423 | 1446 | defer tmp.cleanup(); |
| 1424 | 1447 | const file = try tmp.dir.createFile("test_file", .{ .read = true }); |
| 1448 | defer file.close(); | |
| 1425 | 1449 | // Create a file and make it read-only |
| 1426 | 1450 | const metadata = try file.metadata(); |
| 1427 | 1451 | var permissions = metadata.permissions(); |
| 1428 | 1452 | permissions.setReadOnly(true); |
| 1429 | 1453 | try file.setPermissions(permissions); |
| 1430 | try testing.expectError(error.AccessDenied, tmp.dir.deleteFile("test_file")); | |
| 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"); | |
| 1454 | try tmp.dir.deleteFile("test_file"); // file is unmapped and deleted once last handle closed | |
| 1436 | 1455 | } |
| 1437 | 1456 | |
| 1438 | 1457 | test "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 | 938 | else => return unexpectedStatus(rc), |
| 939 | 939 | } |
| 940 | 940 | defer CloseHandle(tmp_handle); |
| 941 | ||
| 941 | 942 | if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) { |
| 942 | 943 | // Deletion with posix semantics. |
| 943 | 944 | var info = FILE_DISPOSITION_INFORMATION_EX{ |
| ... | ... | @@ -953,17 +954,13 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 953 | 954 | @sizeOf(FILE_DISPOSITION_INFORMATION_EX), |
| 954 | 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 | 957 | } else { |
| 962 | 958 | // Deletion with file pending semantics, which requires waiting or moving |
| 963 | 959 | // files to get them removed (from here). |
| 964 | 960 | var file_dispo = FILE_DISPOSITION_INFORMATION{ |
| 965 | 961 | .DeleteFile = TRUE, |
| 966 | 962 | }; |
| 963 | ||
| 967 | 964 | rc = ntdll.NtSetInformationFile( |
| 968 | 965 | tmp_handle, |
| 969 | 966 | &io, |
| ... | ... | @@ -971,15 +968,15 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 971 | 968 | @sizeOf(FILE_DISPOSITION_INFORMATION), |
| 972 | 969 | .FileDispositionInformation, |
| 973 | 970 | ); |
| 974 | switch (rc) { | |
| 975 | .SUCCESS => {}, | |
| 976 | .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, | |
| 977 | .INVALID_PARAMETER => unreachable, | |
| 978 | .CANNOT_DELETE => return error.AccessDenied, | |
| 979 | .MEDIA_WRITE_PROTECTED => return error.AccessDenied, | |
| 980 | .ACCESS_DENIED => return error.AccessDenied, | |
| 981 | else => return unexpectedStatus(rc), | |
| 982 | } | |
| 971 | } | |
| 972 | switch (rc) { | |
| 973 | .SUCCESS => {}, | |
| 974 | .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, | |
| 975 | .INVALID_PARAMETER => unreachable, | |
| 976 | .CANNOT_DELETE => return error.AccessDenied, | |
| 977 | .MEDIA_WRITE_PROTECTED => return error.AccessDenied, | |
| 978 | .ACCESS_DENIED => return error.AccessDenied, | |
| 979 | else => return unexpectedStatus(rc), | |
| 983 | 980 | } |
| 984 | 981 | } |
| 985 | 982 |