type Reader … type fileReader … // NewReader creates a new [Reader] reading from r. func NewReader(r io.Reader) *Reader { … } // Next advances to the next entry in the tar archive. // The Header.Size determines how many bytes can be read for the next file. // Any remaining data in the current file is automatically discarded. // At the end of the archive, Next returns the error io.EOF. // // If Next encounters a non-local name (as defined by [filepath.IsLocal]) // and the GODEBUG environment variable contains `tarinsecurepath=0`, // Next returns the header with an [ErrInsecurePath] error. // A future version of Go may introduce this behavior by default. // Programs that want to accept non-local names can ignore // the [ErrInsecurePath] error and use the returned header. func (tr *Reader) Next() (*Header, error) { … } func (tr *Reader) next() (*Header, error) { … } // handleRegularFile sets up the current file reader and padding such that it // can only read the following logical data section. It will properly handle // special headers that contain no data section. func (tr *Reader) handleRegularFile(hdr *Header) error { … } // handleSparseFile checks if the current file is a sparse format of any type // and sets the curr reader appropriately. func (tr *Reader) handleSparseFile(hdr *Header, rawHdr *block) error { … } // readGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. // If they are found, then this function reads the sparse map and returns it. // This assumes that 0.0 headers have already been converted to 0.1 headers // by the PAX header parsing logic. func (tr *Reader) readGNUSparsePAXHeaders(hdr *Header) (sparseDatas, error) { … } // mergePAX merges paxHdrs into hdr for all relevant fields of Header. func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) { … } // parsePAX parses PAX headers. // If an extended header (type 'x') is invalid, ErrHeader is returned. func parsePAX(r io.Reader) (map[string]string, error) { … } // readHeader reads the next block header and assumes that the underlying reader // is already aligned to a block boundary. It returns the raw block of the // header in case further processing is required. // // The err will be set to io.EOF only when one of the following occurs: // - 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) { … } // readOldGNUSparseMap reads the sparse map from the old GNU sparse format. // The sparse map is stored in the tar header if it's small enough. // If it's larger than four entries, then one or more extension headers are used // to store the rest of the sparse map. // // The Header.Size does not reflect the size of any extended headers used. // Thus, this function will read from the raw io.Reader to fetch extra headers. // This method mutates blk in the process. func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) (sparseDatas, error) { … } // readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format // version 1.0. The format of the sparse map consists of a series of // newline-terminated numeric fields. The first field is the number of entries // and is always present. Following this are the entries, consisting of two // fields (offset, length). This function must stop reading at the end // boundary of the block containing the last newline. // // Note that the GNU manual says that numeric values should be encoded in octal // format. However, the GNU tar utility itself outputs these values in decimal. // As such, this library treats values as being encoded in decimal. func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { … } // readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format // version 0.1. The sparse map is stored in the PAX headers. func readGNUSparseMap0x1(paxHdrs map[string]string) (sparseDatas, error) { … } // Read reads from the current file in the tar archive. // It returns (0, io.EOF) when it reaches the end of that file, // until [Next] is called to advance to the next file. // // If the current file is sparse, then the regions marked as a hole // are read back as NUL-bytes. // // Calling Read on special types like [TypeLink], [TypeSymlink], [TypeChar], // [TypeBlock], [TypeDir], and [TypeFifo] returns (0, [io.EOF]) regardless of what // the [Header.Size] claims. func (tr *Reader) Read(b []byte) (int, error) { … } // writeTo writes the content of the current file to w. // The bytes written matches the number of remaining bytes in the current file. // // If the current file is sparse and w is an io.WriteSeeker, // then writeTo uses Seek to skip past holes defined in Header.SparseHoles, // assuming that skipped regions are filled with NULs. // This always writes the last byte to ensure w is the right size. // // TODO(dsnet): Re-export this when adding sparse file support. // See https://golang.org/issue/22735 func (tr *Reader) writeTo(w io.Writer) (int64, error) { … } type regFileReader … func (fr *regFileReader) Read(b []byte) (n int, err error) { … } func (fr *regFileReader) WriteTo(w io.Writer) (int64, error) { … } // logicalRemaining implements fileState.logicalRemaining. func (fr regFileReader) logicalRemaining() int64 { … } // physicalRemaining implements fileState.physicalRemaining. func (fr regFileReader) physicalRemaining() int64 { … } type sparseFileReader … func (sr *sparseFileReader) Read(b []byte) (n int, err error) { … } func (sr *sparseFileReader) WriteTo(w io.Writer) (n int64, err error) { … } func (sr sparseFileReader) logicalRemaining() int64 { … } func (sr sparseFileReader) physicalRemaining() int64 { … } type zeroReader … func (zeroReader) Read(b []byte) (int, error) { … } // mustReadFull is like io.ReadFull except it returns // io.ErrUnexpectedEOF when io.EOF is hit before len(b) bytes are read. func mustReadFull(r io.Reader, b []byte) (int, error) { … } // tryReadFull is like io.ReadFull except it returns // io.EOF when it is hit before len(b) bytes are read. func tryReadFull(r io.Reader, b []byte) (n int, err error) { … } // readSpecialFile is like io.ReadAll except it returns // ErrFieldTooLong if more than maxSpecialFileSize is read. func readSpecialFile(r io.Reader) ([]byte, error) { … } // discard skips n bytes in r, reporting an error if unable to do so. func discard(r io.Reader, n int64) error { … }