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>
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)
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
}, {
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 {
// 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