From e46a815cbcaa5270acfb2893b66791150f4d2a87 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 11 Aug 2015 15:51:52 -0400 Subject: [PATCH] archive/tar: fix carry-over of bytes for GNU types Archives produced with GNU tar can have types of TypeGNULongName and TypeGNULongLink. These fields effectively appear like two file entries in the tar archive. While golang's `archive/tar` transparently provide the file name and headers and file payload, the access to the raw bytes is still needed. This fixes the access to the longlink header, it's payload (of the long file path name), and the following file header and actual file payload. --- archive/tar/reader.go | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/archive/tar/reader.go b/archive/tar/reader.go index a89957e..f817956 100644 --- a/archive/tar/reader.go +++ b/archive/tar/reader.go @@ -154,44 +154,60 @@ func (tr *Reader) Next() (*Header, error) { } return hdr, nil case TypeGNULongName: + var b *bytes.Buffer + if tr.RawAccounting { + b = bytes.NewBuffer(tr.RawBytes()) + } // We have a GNU long name header. Its contents are the real file name. realname, err := ioutil.ReadAll(tr) if err != nil { return nil, err } - var b []byte if tr.RawAccounting { + if _, err = tr.rawBytes.Write(b.Bytes()); err != nil { + return nil, err + } if _, err = tr.rawBytes.Write(realname); err != nil { return nil, err } - b = tr.RawBytes() + b.Reset() + b.Write(tr.RawBytes()) } hdr, err := tr.Next() // since the above call to Next() resets the buffer, we need to throw the bytes over if tr.RawAccounting { - if _, err = tr.rawBytes.Write(b); err != nil { + b.Write(tr.RawBytes()) + if _, err = tr.rawBytes.Write(b.Bytes()); err != nil { return nil, err } } hdr.Name = cString(realname) return hdr, err case TypeGNULongLink: + var b *bytes.Buffer + if tr.RawAccounting { + b = bytes.NewBuffer(tr.RawBytes()) + } // We have a GNU long link header. realname, err := ioutil.ReadAll(tr) if err != nil { return nil, err } - var b []byte if tr.RawAccounting { + if _, err = tr.rawBytes.Write(b.Bytes()); err != nil { + return nil, err + } if _, err = tr.rawBytes.Write(realname); err != nil { return nil, err } - b = tr.RawBytes() + b.Reset() + b.Write(tr.RawBytes()) } hdr, err := tr.Next() // since the above call to Next() resets the buffer, we need to throw the bytes over if tr.RawAccounting { - if _, err = tr.rawBytes.Write(b); err != nil { + b.Write(tr.RawBytes()) + if _, err = tr.rawBytes.Write(b.Bytes()); err != nil { return nil, err } }