Skip to content

Commit 6069680

Browse files
authored
ZipFile UnixCreateSetsPermissionsInExternalAttributes test fails on Apple OSes (#69583)
* ZipFile UnixCreateSetsPermissionsInExternalAttributes test fails on Apple OSes There are scenarios where chmod succeeds, but the OS clears certain bits, like S_ISGID and S_ISUID. When this happens, the ZipFile tests fail because the .zip file doesn't contain the expected ExternalAttributes. To fix this, read the file mode after calling chmod, and update the expected file mode so the tests still pass. Fix #68293 Fix #60581 * Fix the tests to expect the correct file name
1 parent e7886b2 commit 6069680

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,21 @@ namespace System.IO.Compression.Tests
1212
public partial class ZipFile_Unix : ZipFileTestBase
1313
{
1414
[Fact]
15-
[ActiveIssue("https://github.com/dotnet/runtime/issues/68293", TestPlatforms.OSX)]
16-
[ActiveIssue("https://github.com/dotnet/runtime/issues/60581", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)]
1715
public void UnixCreateSetsPermissionsInExternalAttributes()
1816
{
1917
// '7600' tests that S_ISUID, S_ISGID, and S_ISVTX bits get preserved in ExternalAttributes
2018
string[] testPermissions = new[] { "777", "755", "644", "600", "7600" };
2119

2220
using (var tempFolder = new TempDirectory(Path.Combine(GetTestFilePath(), "testFolder")))
2321
{
24-
foreach (string permission in testPermissions)
25-
{
26-
CreateFile(tempFolder.Path, permission);
27-
}
22+
string[] expectedPermissions = CreateFiles(tempFolder.Path, testPermissions);
2823

2924
string archivePath = GetTestFilePath();
3025
ZipFile.CreateFromDirectory(tempFolder.Path, archivePath);
3126

3227
using (ZipArchive archive = ZipFile.OpenRead(archivePath))
3328
{
34-
Assert.Equal(5, archive.Entries.Count);
29+
Assert.Equal(expectedPermissions.Length, archive.Entries.Count);
3530

3631
foreach (ZipArchiveEntry entry in archive.Entries)
3732
{
@@ -50,7 +45,7 @@ void EnsureExternalAttributes(string permissions, ZipArchiveEntry entry)
5045
{
5146
ZipFile.ExtractToDirectory(archivePath, extractFolder.Path);
5247

53-
foreach (string permission in testPermissions)
48+
foreach (string permission in expectedPermissions)
5449
{
5550
string filename = Path.Combine(extractFolder.Path, permission + ".txt");
5651
Assert.True(File.Exists(filename));
@@ -96,12 +91,38 @@ public void UnixExtractSetsFilePermissionsFromExternalAttributes()
9691
}
9792
}
9893

99-
private static void CreateFile(string folderPath, string permissions)
94+
private static string[] CreateFiles(string folderPath, string[] testPermissions)
10095
{
101-
string filename = Path.Combine(folderPath, $"{permissions}.txt");
102-
File.WriteAllText(filename, "contents");
96+
string[] expectedPermissions = new string[testPermissions.Length];
97+
98+
for (int i = 0; i < testPermissions.Length; i++)
99+
{
100+
string permissions = testPermissions[i];
101+
string filename = Path.Combine(folderPath, $"{permissions}.txt");
102+
File.WriteAllText(filename, "contents");
103+
104+
Assert.Equal(0, Interop.Sys.ChMod(filename, Convert.ToInt32(permissions, 8)));
105+
106+
// In some environments, the file mode may be modified by the OS.
107+
// See the Rationale section of https://linux.die.net/man/3/chmod.
103108

104-
Assert.Equal(0, Interop.Sys.ChMod(filename, Convert.ToInt32(permissions, 8)));
109+
// To workaround this, read the file mode back, and if it has changed, update the file name
110+
// since the name is used to compare the file mode.
111+
Interop.Sys.FileStatus status;
112+
Assert.Equal(0, Interop.Sys.Stat(filename, out status));
113+
string updatedPermissions = Convert.ToString(status.Mode & 0xFFF, 8);
114+
if (updatedPermissions != permissions)
115+
{
116+
string newFileName = Path.Combine(folderPath, $"{updatedPermissions}.txt");
117+
File.Move(filename, newFileName);
118+
119+
permissions = updatedPermissions;
120+
}
121+
122+
expectedPermissions[i] = permissions;
123+
}
124+
125+
return expectedPermissions;
105126
}
106127

107128
private static void EnsureFilePermissions(string filename, string permissions)

0 commit comments

Comments
 (0)