]> Cypherpunks repositories - gostls13.git/commitdiff
archive/tar: add support for atime and ctime to Writer
authorJoe Tsai <joetsai@digital-static.net>
Mon, 14 Aug 2017 22:39:19 +0000 (15:39 -0700)
committerJoe Tsai <thebrokentoaster@gmail.com>
Tue, 15 Aug 2017 03:07:59 +0000 (03:07 +0000)
Both the GNU and PAX formats support atime and ctime fields.
The implementation is trivial now that we have:
* support for formatting PAX records for timestamps
* dedicated methods that only handle one format (e.g., GNU)

Fixes #17876

Change-Id: I0c604fce14a47d722098afc966399cca2037395d
Reviewed-on: https://go-review.googlesource.com/55570
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/archive/tar/common.go
src/archive/tar/tar_test.go
src/archive/tar/writer.go

index e9dff8439eea16ff7aae0076ec69183b89c08864..fb214c855d1c956d61e623ff25d49252e5ac1089 100644 (file)
@@ -133,8 +133,9 @@ func (h *Header) allowedFormats() (format int, paxHdrs map[string]string) {
        const supportGNULong = false
 
        var blk block
-       var v7 = blk.V7()
-       var ustar = blk.USTAR()
+       v7 := blk.V7()
+       ustar := blk.USTAR()
+       gnu := blk.GNU()
        verifyString(h.Name, len(v7.Name()), supportGNULong, paxPath)
        verifyString(h.Linkname, len(v7.LinkName()), supportGNULong, paxLinkpath)
        verifyString(h.Uname, len(ustar.UserName()), false, paxUname)
@@ -146,9 +147,8 @@ func (h *Header) allowedFormats() (format int, paxHdrs map[string]string) {
        verifyNumeric(h.Devmajor, len(ustar.DevMajor()), paxNone)
        verifyNumeric(h.Devminor, len(ustar.DevMinor()), paxNone)
        verifyTime(h.ModTime, len(v7.ModTime()), true, paxMtime)
-       // TODO(dsnet): Support atime and ctime fields.
-       // verifyTime(h.AccessTime, len(gnu.AccessTime()), false, paxAtime)
-       // verifyTime(h.ChangeTime, len(gnu.ChangeTime()), false, paxCtime)
+       verifyTime(h.AccessTime, len(gnu.AccessTime()), false, paxAtime)
+       verifyTime(h.ChangeTime, len(gnu.ChangeTime()), false, paxCtime)
 
        if !isHeaderOnlyType(h.Typeflag) && h.Size < 0 {
                return formatUnknown, nil
index 79895e6f9deb57358c7843cc80594067735b861e..22e23a6bbdc5fb307e9427bbb883ac3d902f72e1 100644 (file)
@@ -450,6 +450,34 @@ func TestHeaderAllowedFormats(t *testing.T) {
        }, {
                header:  &Header{ModTime: time.Unix(077777777777, 0)},
                formats: formatUSTAR | formatPAX | formatGNU,
+       }, {
+               header:  &Header{ModTime: time.Unix(077777777777+1, 0)},
+               paxHdrs: map[string]string{paxMtime: "8589934592"},
+               formats: formatPAX | formatGNU,
+       }, {
+               header:  &Header{ModTime: time.Unix(math.MaxInt64, 0)},
+               paxHdrs: map[string]string{paxMtime: "9223372036854775807"},
+               formats: formatPAX | formatGNU,
+       }, {
+               header:  &Header{ModTime: time.Unix(-1, 0)},
+               paxHdrs: map[string]string{paxMtime: "-1"},
+               formats: formatPAX | formatGNU,
+       }, {
+               header:  &Header{ModTime: time.Unix(-1, 500)},
+               paxHdrs: map[string]string{paxMtime: "-0.9999995"},
+               formats: formatPAX,
+       }, {
+               header:  &Header{AccessTime: time.Unix(0, 0)},
+               paxHdrs: map[string]string{paxAtime: "0"},
+               formats: formatPAX | formatGNU,
+       }, {
+               header:  &Header{AccessTime: time.Unix(-123, 0)},
+               paxHdrs: map[string]string{paxAtime: "-123"},
+               formats: formatPAX | formatGNU,
+       }, {
+               header:  &Header{ChangeTime: time.Unix(123, 456)},
+               paxHdrs: map[string]string{paxCtime: "123.000000456"},
+               formats: formatPAX,
        }}
 
        for i, v := range vectors {
index 7d393b46dfcf20af01a7c0779cac8b21bf96affa..3d75c398e976cde5fad76a42904767411a7adeb2 100644 (file)
@@ -141,8 +141,12 @@ func (tw *Writer) writeGNUHeader(hdr *Header) error {
        // Pack the main header.
        var f formatter
        blk := tw.templateV7Plus(hdr, f.formatString, f.formatNumeric)
-       // TODO(dsnet): Support atime and ctime fields.
-       // See https://golang.org/issue/17876
+       if !hdr.AccessTime.IsZero() {
+               f.formatNumeric(blk.GNU().AccessTime(), hdr.AccessTime.Unix())
+       }
+       if !hdr.ChangeTime.IsZero() {
+               f.formatNumeric(blk.GNU().ChangeTime(), hdr.ChangeTime.Unix())
+       }
        blk.SetFormat(formatGNU)
        if f.err != nil {
                return f.err // Should never happen since header is validated