From 24fae6b6d0478ceb9a15a078af244f9e6707f670 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Wed, 8 Dec 2021 17:32:43 -0500 Subject: [PATCH] tar.Reader(): add NextHeader() Add a NextHeader() to tar.Reader that can reuse a passed-in Header structure. Signed-off-by: Nalin Dahyabhai --- archive/tar/reader.go | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/archive/tar/reader.go b/archive/tar/reader.go index ea64a38..7630334 100644 --- a/archive/tar/reader.go +++ b/archive/tar/reader.go @@ -68,15 +68,25 @@ func NewReader(r io.Reader) *Reader { // // io.EOF is returned at the end of the input. func (tr *Reader) Next() (*Header, error) { + return tr.NextHeader(nil) +} + +// NextHeader advances to the next entry in the tar archive, attempting +// to reuse the passed-in Header. +// The Header.Size determines how many bytes can be read for the next file. +// Any remaining data in the current file is automatically discarded. +// +// io.EOF is returned at the end of the input. +func (tr *Reader) NextHeader(h *Header) (*Header, error) { if tr.err != nil { return nil, tr.err } - hdr, err := tr.next() + hdr, err := tr.nextHeader(h) tr.err = err return hdr, err } -func (tr *Reader) next() (*Header, error) { +func (tr *Reader) nextHeader(h *Header) (*Header, error) { var paxHdrs map[string]string var gnuLongName, gnuLongLink string @@ -108,7 +118,7 @@ func (tr *Reader) next() (*Header, error) { } tr.pad = 0 - hdr, rawHdr, err := tr.readHeader() + hdr, rawHdr, err := tr.readHeader(h) if err != nil { return nil, err } @@ -127,13 +137,14 @@ func (tr *Reader) next() (*Header, error) { } if hdr.Typeflag == TypeXGlobalHeader { mergePAX(hdr, paxHdrs) - return &Header{ + *hdr = Header{ Name: hdr.Name, Typeflag: hdr.Typeflag, Xattrs: hdr.Xattrs, PAXRecords: hdr.PAXRecords, Format: format, - }, nil + } + return hdr, nil } continue // This is a meta header affecting the next header case TypeGNULongName, TypeGNULongLink: @@ -384,7 +395,7 @@ func parsePAX(r io.Reader) (map[string]string, error) { // * Exactly 0 bytes are read and EOF is hit. // * Exactly 1 block of zeros is read and EOF is hit. // * At least 2 blocks of zeros are read. -func (tr *Reader) readHeader() (*Header, *block, error) { +func (tr *Reader) readHeader(h *Header) (*Header, *block, error) { // Two blocks of zero bytes marks the end of the archive. n, err := io.ReadFull(tr.r, tr.blk[:]) if tr.RawAccounting && (err == nil || err == io.EOF) { @@ -415,7 +426,13 @@ func (tr *Reader) readHeader() (*Header, *block, error) { } var p parser - hdr := new(Header) + var hdr *Header + if h != nil { + *h = Header{} + hdr = h + } else { + hdr = new(Header) + } // Unpack the V7 header. v7 := tr.blk.V7()