Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Tar extraction should set tar-level timestamps #212

Closed
lissyx opened this issue Feb 18, 2020 · 3 comments
Closed

Tar extraction should set tar-level timestamps #212

lissyx opened this issue Feb 18, 2020 · 3 comments

Comments

@lissyx
Copy link

lissyx commented Feb 18, 2020

What would you like to have changed?

When extracting a tar (or tar composition, i.e., tar.xz, tar.gz, tar.bz2, etc), I would like the extracted files to have the proper timestamps (atime, mtime) that were recorded in the file

Why is this feature a useful, necessary, and/or important addition to this project?

This is the behavior of GNU tar, and lacking this feature breaks some usecases

What alternatives are there, or what are you doing in the meantime to work around the lack of this feature?

I can't use a tar of bazel's cache via generic-worker project (https://github.com/taskcluster/taskcluster/blob/222e8057550e7560412920446e76076d3db8e496/workers/generic-worker/mounts.go#L670-L679): newer timestamps breaks sanity checks from Bazel.

@lissyx
Copy link
Author

lissyx commented Feb 18, 2020

I tried to make something that works pretty well in my case, but I'm really not at ease with Go to do more:

diff --git a/tar.go b/tar.go
index 6dda50a..d8ef9b0 100644
--- a/tar.go
+++ b/tar.go
@@ -230,16 +230,27 @@ func (t *Tar) untarFile(f File, destination string, hdr *tar.Header) error {
        case tar.TypeDir:
                return mkdir(to, f.Mode())
        case tar.TypeReg, tar.TypeRegA, tar.TypeChar, tar.TypeBlock, tar.TypeFifo, tar.TypeGNUSparse:
-               return writeNewFile(to, f, f.Mode())
+               err := writeNewFile(to, f, f.Mode())
+               if err == nil {
+                       return os.Chtimes(to, hdr.ModTime, hdr.ModTime)
+               }
        case tar.TypeSymlink:
-               return writeNewSymbolicLink(to, hdr.Linkname)
+               err := writeNewSymbolicLink(to, hdr.Linkname)
+               if err == nil {
+                       return os.Chtimes(to, hdr.ModTime, hdr.ModTime)
+               }
        case tar.TypeLink:
-               return writeNewHardLink(to, filepath.Join(destination, hdr.Linkname))
+               err := writeNewHardLink(to, filepath.Join(destination, hdr.Linkname))
+               if err == nil {
+                       return os.Chtimes(destination, hdr.ModTime, hdr.ModTime)
+               }
        case tar.TypeXGlobalHeader:
                return nil // ignore the pax global header from git-generated tarballs
        default:
                return fmt.Errorf("%s: unknown type flag: %c", hdr.Name, hdr.Typeflag)
        }
+
+       return nil
 }
 
 func (t *Tar) writeWalk(source, topLevelFolder, destination string) error {

@mholt
Copy link
Owner

mholt commented Jan 2, 2022

Thanks for contributing a patch!

I've completely rewritten this library with some much needed improvements in #302, which will become v4 of this package. The new core APIs no longer write to disk, so this issue becomes irrelevant, as it is currently up to the user to write streams to disk in the way they want to. Maybe in the future there will be some helper functions or CLI commands to do this, at which point we can reassess; but for now I suppose this can be closed. Feel free to continue discussion and we can reopen if needed.

@mholt mholt closed this as completed Jan 2, 2022
@lissyx
Copy link
Author

lissyx commented Jan 2, 2022

Thanks, unfortunately I've moved topics and i dont depend on that anymore so i cant really continue to discuss that 😊

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants