Skip to content

Commit eaaed2a

Browse files
committed
Merge in 'release/7.0' changes
2 parents 0f05efe + 170dd10 commit eaaed2a

File tree

3 files changed

+285
-10
lines changed

3 files changed

+285
-10
lines changed

src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,36 +59,69 @@ protected int CreateGroup(string groupName)
5959
return GetGroupId(groupName);
6060
}
6161

62+
protected int CreateUser(string userName)
63+
{
64+
Execute("useradd", userName);
65+
return GetUserId(userName);
66+
}
67+
6268
protected int GetGroupId(string groupName)
6369
{
6470
string standardOutput = Execute("getent", $"group {groupName}");
6571
string[] values = standardOutput.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
6672
return int.Parse(values[^1]);
6773
}
68-
74+
75+
protected int GetUserId(string userName)
76+
{
77+
string standardOutput = Execute("id", $"-u {userName}");
78+
return int.Parse(standardOutput);
79+
}
80+
6981
protected void SetGroupAsOwnerOfFile(string groupName, string filePath) =>
7082
Execute("chgrp", $"{groupName} {filePath}");
7183

84+
protected void SetUserAsOwnerOfFile(string userName, string filePath) =>
85+
Execute("chown", $"{userName} {filePath}");
7286

73-
protected void DeleteGroup(string groupName) =>
87+
protected void DeleteGroup(string groupName)
88+
{
7489
Execute("groupdel", groupName);
90+
Threading.Thread.Sleep(250);
91+
Assert.Throws<IOException>(() => GetGroupId(groupName));
92+
}
93+
94+
protected void DeleteUser(string userName)
95+
{
96+
Execute("userdel", $"-f {userName}");
97+
Threading.Thread.Sleep(250);
98+
Assert.Throws<IOException>(() => GetUserId(userName));
99+
}
75100

76101
private string Execute(string command, string arguments)
77102
{
78103
using Process p = new Process();
79104

80-
p.StartInfo.UseShellExecute = false;
81105
p.StartInfo.FileName = command;
82106
p.StartInfo.Arguments = arguments;
107+
108+
p.StartInfo.UseShellExecute = false;
83109
p.StartInfo.RedirectStandardOutput = true;
84110
p.StartInfo.RedirectStandardError = true;
85111

112+
string standardError = string.Empty;
113+
p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => { standardError += e.Data; });
114+
115+
string standardOutput = string.Empty;
116+
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => { standardOutput += e.Data; });
117+
86118
p.Start();
119+
120+
p.BeginOutputReadLine();
121+
p.BeginErrorReadLine();
122+
87123
p.WaitForExit();
88124

89-
string standardOutput = p.StandardOutput.ReadToEnd();
90-
string standardError = p.StandardError.ReadToEnd();
91-
92125
if (p.ExitCode != 0)
93126
{
94127
throw new IOException($"Error '{p.ExitCode}' when executing '{command} {arguments}'. Message: {standardError}");

src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using Microsoft.DotNet.RemoteExecutor;
54
using System.IO;
5+
using Microsoft.DotNet.RemoteExecutor;
66
using Xunit;
77

88
namespace System.Formats.Tar.Tests
@@ -177,8 +177,129 @@ public void CreateEntryFromFileOwnedByNonExistentGroup(TarEntryFormat f)
177177
{
178178
PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry;
179179
Assert.NotNull(entry);
180-
Assert.Equal(entry.GroupName, string.Empty);
180+
181+
Assert.Equal(string.Empty, entry.GroupName);
181182
Assert.Equal(groupId, entry.Gid);
183+
184+
string extractedPath = Path.Join(root.Path, "extracted.txt");
185+
entry.ExtractToFile(extractedPath, overwrite: false);
186+
Assert.True(File.Exists(extractedPath));
187+
188+
Assert.Null(reader.GetNextEntry());
189+
}
190+
}, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose();
191+
}
192+
193+
[ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))]
194+
[InlineData(TarEntryFormat.Ustar)]
195+
[InlineData(TarEntryFormat.Pax)]
196+
[InlineData(TarEntryFormat.Gnu)]
197+
public void CreateEntryFromFileOwnedByNonExistentUser(TarEntryFormat f)
198+
{
199+
RemoteExecutor.Invoke((string strFormat) =>
200+
{
201+
using TempDirectory root = new TempDirectory();
202+
203+
string fileName = "file.txt";
204+
string filePath = Path.Join(root.Path, fileName);
205+
File.Create(filePath).Dispose();
206+
207+
string userName = Path.GetRandomFileName()[0..6];
208+
int userId = CreateUser(userName);
209+
210+
try
211+
{
212+
SetUserAsOwnerOfFile(userName, filePath);
213+
}
214+
finally
215+
{
216+
DeleteUser(userName);
217+
}
218+
219+
using MemoryStream archive = new MemoryStream();
220+
using (TarWriter writer = new TarWriter(archive, Enum.Parse<TarEntryFormat>(strFormat), leaveOpen: true))
221+
{
222+
writer.WriteEntry(filePath, fileName); // Should not throw
223+
}
224+
archive.Seek(0, SeekOrigin.Begin);
225+
226+
using (TarReader reader = new TarReader(archive, leaveOpen: false))
227+
{
228+
PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry;
229+
Assert.NotNull(entry);
230+
231+
Assert.Equal(string.Empty, entry.UserName);
232+
Assert.Equal(userId, entry.Uid);
233+
234+
string extractedPath = Path.Join(root.Path, "extracted.txt");
235+
entry.ExtractToFile(extractedPath, overwrite: false);
236+
Assert.True(File.Exists(extractedPath));
237+
238+
Assert.Null(reader.GetNextEntry());
239+
}
240+
}, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose();
241+
}
242+
243+
[ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))]
244+
[InlineData(TarEntryFormat.Ustar)]
245+
[InlineData(TarEntryFormat.Pax)]
246+
[InlineData(TarEntryFormat.Gnu)]
247+
public void CreateEntryFromFileOwnedByNonExistentGroupAndUser(TarEntryFormat f)
248+
{
249+
RemoteExecutor.Invoke((string strFormat) =>
250+
{
251+
using TempDirectory root = new TempDirectory();
252+
253+
string fileName = "file.txt";
254+
string filePath = Path.Join(root.Path, fileName);
255+
File.Create(filePath).Dispose();
256+
257+
string groupName = Path.GetRandomFileName()[0..6];
258+
int groupId = CreateGroup(groupName);
259+
260+
string userName = Path.GetRandomFileName()[0..6];
261+
int userId = CreateUser(userName);
262+
263+
try
264+
{
265+
SetGroupAsOwnerOfFile(groupName, filePath);
266+
}
267+
finally
268+
{
269+
DeleteGroup(groupName);
270+
}
271+
272+
try
273+
{
274+
SetUserAsOwnerOfFile(userName, filePath);
275+
}
276+
finally
277+
{
278+
DeleteUser(userName);
279+
}
280+
281+
using MemoryStream archive = new MemoryStream();
282+
using (TarWriter writer = new TarWriter(archive, Enum.Parse<TarEntryFormat>(strFormat), leaveOpen: true))
283+
{
284+
writer.WriteEntry(filePath, fileName); // Should not throw
285+
}
286+
archive.Seek(0, SeekOrigin.Begin);
287+
288+
using (TarReader reader = new TarReader(archive, leaveOpen: false))
289+
{
290+
PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry;
291+
Assert.NotNull(entry);
292+
293+
Assert.Equal(string.Empty, entry.GroupName);
294+
Assert.Equal(groupId, entry.Gid);
295+
296+
Assert.Equal(string.Empty, entry.UserName);
297+
Assert.Equal(userId, entry.Uid);
298+
299+
string extractedPath = Path.Join(root.Path, "extracted.txt");
300+
entry.ExtractToFile(extractedPath, overwrite: false);
301+
Assert.True(File.Exists(extractedPath));
302+
182303
Assert.Null(reader.GetNextEntry());
183304
}
184305
}, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose();

src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using Microsoft.DotNet.RemoteExecutor;
54
using System.IO;
65
using System.Threading.Tasks;
6+
using Microsoft.DotNet.RemoteExecutor;
77
using Xunit;
88

99
namespace System.Formats.Tar.Tests
@@ -187,8 +187,129 @@ public void CreateEntryFromFileOwnedByNonExistentGroup_Async(TarEntryFormat f)
187187
{
188188
PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry;
189189
Assert.NotNull(entry);
190-
Assert.Equal(entry.GroupName, string.Empty);
190+
191+
Assert.Equal(string.Empty, entry.GroupName);
191192
Assert.Equal(groupId, entry.Gid);
193+
194+
string extractedPath = Path.Join(root.Path, "extracted.txt");
195+
await entry.ExtractToFileAsync(extractedPath, overwrite: false);
196+
Assert.True(File.Exists(extractedPath));
197+
198+
Assert.Null(await reader.GetNextEntryAsync());
199+
}
200+
}, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose();
201+
}
202+
203+
[ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))]
204+
[InlineData(TarEntryFormat.Ustar)]
205+
[InlineData(TarEntryFormat.Pax)]
206+
[InlineData(TarEntryFormat.Gnu)]
207+
public void CreateEntryFromFileOwnedByNonExistentUser_Async(TarEntryFormat f)
208+
{
209+
RemoteExecutor.Invoke(async (string strFormat) =>
210+
{
211+
using TempDirectory root = new TempDirectory();
212+
213+
string fileName = "file.txt";
214+
string filePath = Path.Join(root.Path, fileName);
215+
File.Create(filePath).Dispose();
216+
217+
string userName = Path.GetRandomFileName()[0..6];
218+
int userId = CreateUser(userName);
219+
220+
try
221+
{
222+
SetUserAsOwnerOfFile(userName, filePath);
223+
}
224+
finally
225+
{
226+
DeleteUser(userName);
227+
}
228+
229+
await using MemoryStream archive = new MemoryStream();
230+
await using (TarWriter writer = new TarWriter(archive, Enum.Parse<TarEntryFormat>(strFormat), leaveOpen: true))
231+
{
232+
await writer.WriteEntryAsync(filePath, fileName); // Should not throw
233+
}
234+
archive.Seek(0, SeekOrigin.Begin);
235+
236+
await using (TarReader reader = new TarReader(archive, leaveOpen: false))
237+
{
238+
PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry;
239+
Assert.NotNull(entry);
240+
241+
Assert.Equal(string.Empty, entry.UserName);
242+
Assert.Equal(userId, entry.Uid);
243+
244+
string extractedPath = Path.Join(root.Path, "extracted.txt");
245+
await entry.ExtractToFileAsync(extractedPath, overwrite: false);
246+
Assert.True(File.Exists(extractedPath));
247+
248+
Assert.Null(await reader.GetNextEntryAsync());
249+
}
250+
}, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose();
251+
}
252+
253+
[ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))]
254+
[InlineData(TarEntryFormat.Ustar)]
255+
[InlineData(TarEntryFormat.Pax)]
256+
[InlineData(TarEntryFormat.Gnu)]
257+
public void CreateEntryFromFileOwnedByNonExistentGroupAndUser_Async(TarEntryFormat f)
258+
{
259+
RemoteExecutor.Invoke(async (string strFormat) =>
260+
{
261+
using TempDirectory root = new TempDirectory();
262+
263+
string fileName = "file.txt";
264+
string filePath = Path.Join(root.Path, fileName);
265+
File.Create(filePath).Dispose();
266+
267+
string groupName = Path.GetRandomFileName()[0..6];
268+
int groupId = CreateGroup(groupName);
269+
270+
string userName = Path.GetRandomFileName()[0..6];
271+
int userId = CreateUser(userName);
272+
273+
try
274+
{
275+
SetGroupAsOwnerOfFile(groupName, filePath);
276+
}
277+
finally
278+
{
279+
DeleteGroup(groupName);
280+
}
281+
282+
try
283+
{
284+
SetUserAsOwnerOfFile(userName, filePath);
285+
}
286+
finally
287+
{
288+
DeleteUser(userName);
289+
}
290+
291+
await using MemoryStream archive = new MemoryStream();
292+
await using (TarWriter writer = new TarWriter(archive, Enum.Parse<TarEntryFormat>(strFormat), leaveOpen: true))
293+
{
294+
await writer.WriteEntryAsync(filePath, fileName); // Should not throw
295+
}
296+
archive.Seek(0, SeekOrigin.Begin);
297+
298+
await using (TarReader reader = new TarReader(archive, leaveOpen: false))
299+
{
300+
PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry;
301+
Assert.NotNull(entry);
302+
303+
Assert.Equal(string.Empty, entry.GroupName);
304+
Assert.Equal(groupId, entry.Gid);
305+
306+
Assert.Equal(string.Empty, entry.UserName);
307+
Assert.Equal(userId, entry.Uid);
308+
309+
string extractedPath = Path.Join(root.Path, "extracted.txt");
310+
await entry.ExtractToFileAsync(extractedPath, overwrite: false);
311+
Assert.True(File.Exists(extractedPath));
312+
192313
Assert.Null(await reader.GetNextEntryAsync());
193314
}
194315
}, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose();

0 commit comments

Comments
 (0)