Skip to content

Commit 96ad4fa

Browse files
authored
Set modified timestamps on files being extracted from tar archives (#74400)
1 parent 40749f6 commit 96ad4fa

File tree

5 files changed

+72
-6
lines changed

5 files changed

+72
-6
lines changed

src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ private void ExtractAsRegularFile(string destinationFileName)
529529
DataStream?.CopyTo(fs);
530530
}
531531

532-
ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime);
532+
AttemptSetLastWriteTime(destinationFileName, ModificationTime);
533533
}
534534

535535
// Asynchronously extracts the current entry as a regular file into the specified destination.
@@ -551,7 +551,19 @@ private async Task ExtractAsRegularFileAsync(string destinationFileName, Cancell
551551
}
552552
}
553553

554-
ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime);
554+
AttemptSetLastWriteTime(destinationFileName, ModificationTime);
555+
}
556+
557+
private static void AttemptSetLastWriteTime(string destinationFileName, DateTimeOffset lastWriteTime)
558+
{
559+
try
560+
{
561+
File.SetLastWriteTime(destinationFileName, lastWriteTime.LocalDateTime); // SetLastWriteTime expects local time
562+
}
563+
catch
564+
{
565+
// Some OSes like Android might not support setting the last write time, the extraction should not fail because of that
566+
}
555567
}
556568

557569
private FileStreamOptions CreateFileStreamOptions(bool isAsync)

src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ public void IncludeAllSegmentsOfPath(bool includeBaseDirectory)
194194
Assert.Null(reader.GetNextEntry());
195195
}
196196

197-
[Fact]
197+
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
198198
public void SkipRecursionIntoDirectorySymlinks()
199199
{
200200
using TempDirectory root = new TempDirectory();
@@ -225,7 +225,7 @@ public void SkipRecursionIntoDirectorySymlinks()
225225
Assert.Null(reader.GetNextEntry()); // file.txt should not be found
226226
}
227227

228-
[Fact]
228+
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
229229
public void SkipRecursionIntoBaseDirectorySymlink()
230230
{
231231
using TempDirectory root = new TempDirectory();

src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Tests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public async Task IncludeAllSegmentsOfPath_Async(bool includeBaseDirectory)
238238
}
239239
}
240240

241-
[Fact]
241+
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
242242
public async Task SkipRecursionIntoDirectorySymlinksAsync()
243243
{
244244
using TempDirectory root = new TempDirectory();
@@ -269,7 +269,7 @@ public async Task SkipRecursionIntoDirectorySymlinksAsync()
269269
Assert.Null(await reader.GetNextEntryAsync()); // file.txt should not be found
270270
}
271271

272-
[Fact]
272+
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
273273
public async Task SkipRecursionIntoBaseDirectorySymlinkAsync()
274274
{
275275
using TempDirectory root = new TempDirectory();

src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ public void NonExistentDirectory_Throws()
4444
Assert.Throws<DirectoryNotFoundException>(() => TarFile.ExtractToDirectory(sourceFileName: filePath, destinationDirectoryName: dirPath, overwriteFiles: false));
4545
}
4646

47+
[Fact]
48+
public void SetsLastModifiedTimeOnExtractedFiles()
49+
{
50+
using TempDirectory root = new TempDirectory();
51+
52+
string inDir = Path.Join(root.Path, "indir");
53+
string inFile = Path.Join(inDir, "file");
54+
55+
string tarFile = Path.Join(root.Path, "file.tar");
56+
57+
string outDir = Path.Join(root.Path, "outdir");
58+
string outFile = Path.Join(outDir, "file");
59+
60+
Directory.CreateDirectory(inDir);
61+
File.Create(inFile).Dispose();
62+
var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local);
63+
File.SetLastWriteTime(inFile, dt);
64+
65+
TarFile.CreateFromDirectory(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false);
66+
67+
Directory.CreateDirectory(outDir);
68+
TarFile.ExtractToDirectory(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false);
69+
70+
Assert.True(File.Exists(outFile));
71+
Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity
72+
}
73+
4774
[Theory]
4875
[InlineData(TestTarFormat.v7)]
4976
[InlineData(TestTarFormat.ustar)]

src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,33 @@ public async Task NonExistentDirectory_Throws_Async()
5656
}
5757
}
5858

59+
[Fact]
60+
public async Task SetsLastModifiedTimeOnExtractedFiles()
61+
{
62+
using TempDirectory root = new TempDirectory();
63+
64+
string inDir = Path.Join(root.Path, "indir");
65+
string inFile = Path.Join(inDir, "file");
66+
67+
string tarFile = Path.Join(root.Path, "file.tar");
68+
69+
string outDir = Path.Join(root.Path, "outdir");
70+
string outFile = Path.Join(outDir, "file");
71+
72+
Directory.CreateDirectory(inDir);
73+
File.Create(inFile).Dispose();
74+
var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local);
75+
File.SetLastWriteTime(inFile, dt);
76+
77+
await TarFile.CreateFromDirectoryAsync(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false);
78+
79+
Directory.CreateDirectory(outDir);
80+
await TarFile.ExtractToDirectoryAsync(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false);
81+
82+
Assert.True(File.Exists(outFile));
83+
Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity
84+
}
85+
5986
[Theory]
6087
[InlineData(TestTarFormat.v7)]
6188
[InlineData(TestTarFormat.ustar)]

0 commit comments

Comments
 (0)