diff options
| author | Joe Tsai <joetsai@digital-static.net> | 2017-08-14 00:03:26 -0700 |
|---|---|---|
| committer | Joe Tsai <thebrokentoaster@gmail.com> | 2017-08-14 21:50:56 +0000 |
| commit | ffd9810e5966c8ad972f429866808b73bbefd8bc (patch) | |
| tree | 1f0b25d02f015b3d0e907e07a9d22970f833762b /src/archive | |
| parent | d180d18666e355b52bf12126119416f6b3c6e843 (diff) | |
| download | go-ffd9810e5966c8ad972f429866808b73bbefd8bc.tar.xz | |
archive/tar: implement specialized logic for GNU format
Rather than going through writeHeader, which attempts to handle all formats,
implement writeGNUHeader, which only has an understanding of the GNU format.
Currently, the implementation is nearly identical to writeUSTARHeader, except:
* formatNumeric is used instead of formatOctal
* the GNU magic value is used
This is kept as a separate method since it makes more logical sense
when we add support for sparse files, long filenames, and atime/ctime fields,
which do not affect USTAR.
Updates #12594
Change-Id: I76efc0b39dc649efc22646dfc9867a7c165f34a8
Reviewed-on: https://go-review.googlesource.com/55237
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Diffstat (limited to 'src/archive')
| -rw-r--r-- | src/archive/tar/writer.go | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go index 8572c46335..c4d908c4ea 100644 --- a/src/archive/tar/writer.go +++ b/src/archive/tar/writer.go @@ -89,8 +89,7 @@ func (tw *Writer) WriteHeader(hdr *Header) error { case allowedFormats&formatPAX != 0: return tw.writePAXHeader(&hdrCpy, paxHdrs) case allowedFormats&formatGNU != 0: - // TODO(dsnet): Implement and call specialized writeGNUHeader. - return tw.writeHeader(&hdrCpy, true) + return tw.writeGNUHeader(&hdrCpy) default: return ErrHeader } @@ -102,7 +101,7 @@ func (tw *Writer) writeUSTARHeader(hdr *Header) error { // Pack the main header. var f formatter - blk := tw.templateV7Plus(hdr, &f) + blk := tw.templateV7Plus(hdr, f.formatString, f.formatOctal) blk.SetFormat(formatUSTAR) if f.err != nil { return f.err // Should never happen since header is validated @@ -141,7 +140,7 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { // Pack the main header. var f formatter - blk := tw.templateV7Plus(hdr, &f) + blk := tw.templateV7Plus(hdr, f.formatString, f.formatOctal) blk.SetFormat(formatPAX) if f.err != nil && len(paxHdrs) == 0 { return f.err // Should never happen, otherwise PAX headers would be used @@ -149,12 +148,36 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { return tw.writeRawHeader(blk, hdr.Size) } +func (tw *Writer) writeGNUHeader(hdr *Header) error { + // TODO(dsnet): Support writing sparse files. + // See https://golang.org/issue/13548 + + // TODO(dsnet): Support long filenames (with UTF-8) support. + + // 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 + blk.SetFormat(formatGNU) + if f.err != nil { + return f.err // Should never happen since header is validated + } + return tw.writeRawHeader(blk, hdr.Size) +} + +type ( + stringFormatter func([]byte, string) + numberFormatter func([]byte, int64) +) + // templateV7Plus fills out the V7 fields of a block using values from hdr. // It also fills out fields (uname, gname, devmajor, devminor) that are -// shared in the USTAR, PAX, and GNU formats. +// shared in the USTAR, PAX, and GNU formats using the provided formatters. // -// The block returned is only valid until the next call to templateV7Plus. -func (tw *Writer) templateV7Plus(hdr *Header, f *formatter) *block { +// The block returned is only valid until the next call to +// templateV7Plus or writeRawFile. +func (tw *Writer) templateV7Plus(hdr *Header, fmtStr stringFormatter, fmtNum numberFormatter) *block { tw.blk.Reset() modTime := hdr.ModTime @@ -164,19 +187,19 @@ func (tw *Writer) templateV7Plus(hdr *Header, f *formatter) *block { v7 := tw.blk.V7() v7.TypeFlag()[0] = hdr.Typeflag - f.formatString(v7.Name(), hdr.Name) - f.formatString(v7.LinkName(), hdr.Linkname) - f.formatOctal(v7.Mode(), hdr.Mode) - f.formatOctal(v7.UID(), int64(hdr.Uid)) - f.formatOctal(v7.GID(), int64(hdr.Gid)) - f.formatOctal(v7.Size(), hdr.Size) - f.formatOctal(v7.ModTime(), modTime.Unix()) + fmtStr(v7.Name(), hdr.Name) + fmtStr(v7.LinkName(), hdr.Linkname) + fmtNum(v7.Mode(), hdr.Mode) + fmtNum(v7.UID(), int64(hdr.Uid)) + fmtNum(v7.GID(), int64(hdr.Gid)) + fmtNum(v7.Size(), hdr.Size) + fmtNum(v7.ModTime(), modTime.Unix()) ustar := tw.blk.USTAR() - f.formatString(ustar.UserName(), hdr.Uname) - f.formatString(ustar.GroupName(), hdr.Gname) - f.formatOctal(ustar.DevMajor(), hdr.Devmajor) - f.formatOctal(ustar.DevMinor(), hdr.Devminor) + fmtStr(ustar.UserName(), hdr.Uname) + fmtStr(ustar.GroupName(), hdr.Gname) + fmtNum(ustar.DevMajor(), hdr.Devmajor) + fmtNum(ustar.DevMinor(), hdr.Devminor) return &tw.blk } |
