-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tar: set directory modification times while extracting. #88231
Conversation
Tagging subscribers to this area: @dotnet/area-system-formats-tar Issue DetailsFixes #74398.
|
c344f07
to
68c408b
Compare
The test I've included fails on Windows. It can be a bug in the implementation, though I expect that would also happen on Linux. |
src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs
Outdated
Show resolved
Hide resolved
I didn't look carefully, but I don't see you setting the directory times (Directory.SetLastWriteTime(..)). Without that, the directories are going to have the same time of the last write to a file within them, I think. (Although I thought that was true on Linux, so not sure why it would be only on Windows) |
src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs
Show resolved
Hide resolved
Co-authored-by: Dan Moseley <danmose@microsoft.com>
Looks like Directory.SetXx must be used to set a directory timestamp. File.SetXx will not work because Windows requires one extra flag: runtime/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs Line 223 in e80ef86
While on Unix, it looks like either work, they end up calling utimensat the same way. |
Yes, that makes the difference. The tests are passing now on Windows too. |
=> c == Path.DirectorySeparatorChar; | ||
} | ||
|
||
private static void AttemptDirectorySetLastWriteTime(string fullPath, DateTimeOffset lastWriteTime) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is copied and changed for directories from:
runtime/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs
Lines 552 to 562 in e80ef86
private static void AttemptSetLastWriteTime(string destinationFileName, DateTimeOffset lastWriteTime) | |
{ | |
try | |
{ | |
File.SetLastWriteTime(destinationFileName, lastWriteTime.LocalDateTime); // SetLastWriteTime expects local time | |
} | |
catch | |
{ | |
// Some OSes like Android might not support setting the last write time, the extraction should not fail because of that | |
} | |
} |
When we close this issue we probably should open an issue for our zip implementation as well as that's also mentioned in that issue |
@@ -285,42 +285,44 @@ public Task ExtractToFileAsync(string destinationFileName, bool overwrite, Cance | |||
internal abstract bool IsDataStreamSetterSupported(); | |||
|
|||
// Extracts the current entry to a location relative to the specified directory. | |||
internal void ExtractRelativeToDirectory(string destinationDirectoryPath, bool overwrite, SortedDictionary<string, UnixFileMode>? pendingModes) | |||
internal void ExtractRelativeToDirectory(string destinationDirectoryPath, bool overwrite, SortedDictionary<string, UnixFileMode>? pendingModes, Stack<(string, DateTimeOffset)> directoryModificationTimes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be reading this wrong but isn't directoryModificationTimes
always empty here with the current implementation? If it's always empty, why even pass it in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It gets new-ed up by the caller of this method and the same instance is passed to all entries of the archive.
Items get added and removed by the call to TarHelpers.UpdatePendingModificationTimes
in this method.
Fixes #74398.