Functions
AddFS
method
#
AddFS adds the files from fs.FS to the archive.
It walks the directory tree starting at the root of the filesystem
adding each file to the tar archive while maintaining the directory structure.
func (tw *Writer) AddFS(fsys fs.FS) error
Close
method
#
Close closes the tar archive by flushing the padding, and writing the footer.
If the current file (from a prior call to [Writer.WriteHeader]) is not fully written,
then this returns an error.
func (tw *Writer) Close() error
Error
method
#
func (he headerError) Error() string
FileInfo
method
#
FileInfo returns an fs.FileInfo for the Header.
func (h *Header) FileInfo() fs.FileInfo
Flush
method
#
Flush finishes writing the current file's block padding.
The current file must be fully written before Flush can be called.
This is unnecessary as the next call to [Writer.WriteHeader] or [Writer.Close]
will implicitly flush out the file's padding.
func (tw *Writer) Flush() error
IsDir
method
#
func (fi headerFileInfo) IsDir() bool
ModTime
method
#
func (fi headerFileInfo) ModTime() time.Time
Mode
method
#
Mode returns the permission and mode bits for the headerFileInfo.
func (fi headerFileInfo) Mode() (mode fs.FileMode)
Name
method
#
Name returns the base name of the file.
func (fi headerFileInfo) Name() string
NewReader
function
#
NewReader creates a new [Reader] reading from r.
func NewReader(r io.Reader) *Reader
NewWriter
function
#
NewWriter creates a new Writer writing to w.
func NewWriter(w io.Writer) *Writer
Next
method
#
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)
Read
method
#
func (sr *sparseFileReader) Read(b []byte) (n int, err error)
Read
method
#
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)
Read
method
#
func (fr *regFileReader) Read(b []byte) (n int, err error)
Read
method
#
func (zeroReader) Read(b []byte) (int, error)
ReadFrom
method
#
func (sw *sparseFileWriter) ReadFrom(r io.Reader) (n int64, err error)
ReadFrom
method
#
func (fw *regFileWriter) ReadFrom(r io.Reader) (int64, error)
Size
method
#
func (fi headerFileInfo) Size() int64
String
method
#
func (fi headerFileInfo) String() string
String
method
#
func (f Format) String() string
Sys
method
#
func (fi headerFileInfo) Sys() any
Write
method
#
func (zeroWriter) Write(b []byte) (int, error)
Write
method
#
func (sw *sparseFileWriter) Write(b []byte) (n int, err error)
Write
method
#
func (fw *regFileWriter) Write(b []byte) (n int, err error)
Write
method
#
Write writes to the current file in the tar archive.
Write returns the error [ErrWriteTooLong] if more than
Header.Size bytes are written after [Writer.WriteHeader].
Calling Write on special types like [TypeLink], [TypeSymlink], [TypeChar],
[TypeBlock], [TypeDir], and [TypeFifo] returns (0, [ErrWriteTooLong]) regardless
of what the [Header.Size] claims.
func (tw *Writer) Write(b []byte) (int, error)
WriteTo
method
#
func (sr *sparseFileReader) WriteTo(w io.Writer) (n int64, err error)
WriteTo
method
#
func (fr *regFileReader) WriteTo(w io.Writer) (int64, error)
accessTime
method
#
func (h *headerSTAR) accessTime() []byte
accessTime
method
#
func (h *headerGNU) accessTime() []byte
alignSparseEntries
function
#
alignSparseEntries mutates src and returns dst where each fragment's
starting offset is aligned up to the nearest block edge, and each
ending offset is aligned down to the nearest block edge.
Even though the Go tar Reader and the BSD tar utility can handle entries
with arbitrary offsets and lengths, the GNU tar utility can only handle
offsets and lengths that are multiples of blockSize.
func alignSparseEntries(src []sparseEntry, size int64) []sparseEntry
allowedFormats
method
#
allowedFormats determines which formats can be used.
The value returned is the logical OR of multiple possible formats.
If the value is FormatUnknown, then the input Header cannot be encoded
and an error is returned explaining why.
As a by-product of checking the fields, this function returns paxHdrs, which
contain all fields that could not be directly encoded.
A value receiver ensures that this method does not mutate the source Header.
func (h Header) allowedFormats() (format Format, paxHdrs map[string]string, err error)
blockPadding
function
#
blockPadding computes the number of bytes needed to pad offset up to the
nearest block edge where 0 <= n < blockSize.
func blockPadding(offset int64) (n int64)
changeTime
method
#
func (h *headerGNU) changeTime() []byte
changeTime
method
#
func (h *headerSTAR) changeTime() []byte
chksum
method
#
func (h *headerV7) chksum() []byte
computeChecksum
method
#
computeChecksum computes the checksum for the header block.
POSIX specifies a sum of the unsigned byte values, but the Sun tar used
signed byte values.
We compute and return both.
func (b *block) computeChecksum() (unsigned int64, signed int64)
devMajor
method
#
func (h *headerSTAR) devMajor() []byte
devMajor
method
#
func (h *headerGNU) devMajor() []byte
devMajor
method
#
func (h *headerUSTAR) devMajor() []byte
devMinor
method
#
func (h *headerSTAR) devMinor() []byte
devMinor
method
#
func (h *headerUSTAR) devMinor() []byte
devMinor
method
#
func (h *headerGNU) devMinor() []byte
discard
function
#
discard skips n bytes in r, reporting an error if unable to do so.
func discard(r io.Reader, n int64) error
endOffset
method
#
func (s sparseEntry) endOffset() int64
ensureEOF
function
#
ensureEOF checks whether r is at EOF, reporting ErrWriteTooLong if not so.
func ensureEOF(r io.Reader) error
entry
method
#
func (s sparseArray) entry(i int) sparseElem
fitsInBase256
function
#
fitsInBase256 reports whether x can be encoded into n bytes using base-256
encoding. Unlike octal encoding, base-256 encoding does not require that the
string ends with a NUL character. Thus, all n bytes are available for output.
If operating in binary mode, this assumes strict GNU binary mode; which means
that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
equivalent to the sign bit in two's complement form.
func fitsInBase256(n int, x int64) bool
fitsInOctal
function
#
fitsInOctal reports whether the integer x fits in a field n-bytes long
using octal encoding with the appropriate NUL terminator.
func fitsInOctal(n int, x int64) bool
formatNumeric
method
#
formatNumeric encodes x into b using base-8 (octal) encoding if possible.
Otherwise it will attempt to use base-256 (binary) encoding.
func (f *formatter) formatNumeric(b []byte, x int64)
formatOctal
method
#
func (f *formatter) formatOctal(b []byte, x int64)
formatPAXRecord
function
#
formatPAXRecord formats a single PAX record, prefixing it with the
appropriate length.
func formatPAXRecord(k string, v string) (string, error)
formatPAXTime
function
#
formatPAXTime converts ts into a time of the form %d.%d as described in the
PAX specification. This function is capable of negative timestamps.
func formatPAXTime(ts time.Time) (s string)
formatString
method
#
formatString copies s into b, NUL-terminating if possible.
func (f *formatter) formatString(b []byte, s string)
getFormat
method
#
getFormat checks that the block is a valid tar header based on the checksum.
It then attempts to guess the specific format based on magic values.
If the checksum fails, then FormatUnknown is returned.
func (b *block) getFormat() Format
gid
method
#
func (h *headerV7) gid() []byte
groupName
method
#
func (h *headerSTAR) groupName() []byte
groupName
method
#
func (h *headerUSTAR) groupName() []byte
groupName
method
#
func (h *headerGNU) groupName() []byte
handleRegularFile
method
#
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
method
#
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
has
method
#
func (f Format) has(f2 Format) bool
hasNUL
function
#
hasNUL reports whether the NUL character exists within s.
func hasNUL(s string) bool
init
function
#
func init()
invertSparseEntries
function
#
invertSparseEntries converts a sparse map from one form to the other.
If the input is sparseHoles, then it will output sparseDatas and vice-versa.
The input must have been already validated.
This function mutates src and returns a normalized map where:
- adjacent fragments are coalesced together
- only the last fragment may be empty
- the endOffset of the last fragment is the total size
func invertSparseEntries(src []sparseEntry, size int64) []sparseEntry
isASCII
function
#
isASCII reports whether the input is an ASCII C-style string.
func isASCII(s string) bool
isExtended
method
#
func (s sparseArray) isExtended() []byte
length
method
#
func (s sparseElem) length() []byte
linkName
method
#
func (h *headerV7) linkName() []byte
logicalRemaining
method
#
logicalRemaining implements fileState.logicalRemaining.
func (fw regFileWriter) logicalRemaining() int64
logicalRemaining
method
#
func (sw sparseFileWriter) logicalRemaining() int64
logicalRemaining
method
#
logicalRemaining implements fileState.logicalRemaining.
func (fr regFileReader) logicalRemaining() int64
logicalRemaining
method
#
func (sr sparseFileReader) logicalRemaining() int64
magic
method
#
func (h *headerGNU) magic() []byte
magic
method
#
func (h *headerUSTAR) magic() []byte
magic
method
#
func (h *headerSTAR) magic() []byte
maxEntries
method
#
func (s sparseArray) maxEntries() int
mayBe
method
#
func (f *Format) mayBe(f2 Format)
mayOnlyBe
method
#
func (f *Format) mayOnlyBe(f2 Format)
mergePAX
function
#
mergePAX merges paxHdrs into hdr for all relevant fields of Header.
func mergePAX(hdr *Header, paxHdrs map[string]string) (err error)
modTime
method
#
func (h *headerV7) modTime() []byte
mode
method
#
func (h *headerV7) mode() []byte
mustNotBe
method
#
func (f *Format) mustNotBe(f2 Format)
mustReadFull
function
#
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)
name
method
#
func (h *headerV7) name() []byte
next
method
#
func (tr *Reader) next() (*Header, error)
offset
method
#
func (s sparseElem) offset() []byte
parseNumeric
method
#
parseNumeric parses the input as being encoded in either base-256 or octal.
This function may return negative numbers.
If parsing fails or an integer overflow occurs, err will be set.
func (p *parser) parseNumeric(b []byte) int64
parseOctal
method
#
func (p *parser) parseOctal(b []byte) int64
parsePAX
function
#
parsePAX parses PAX headers.
If an extended header (type 'x') is invalid, ErrHeader is returned.
func parsePAX(r io.Reader) (map[string]string, error)
parsePAXRecord
function
#
parsePAXRecord parses the input PAX record string into a key-value pair.
If parsing is successful, it will slice off the currently read record and
return the remainder as r.
func parsePAXRecord(s string) (k string, v string, r string, err error)
parsePAXTime
function
#
parsePAXTime takes a string of the form %d.%d as described in the PAX
specification. Note that this implementation allows for negative timestamps,
which is allowed for by the PAX specification, but not always portable.
func parsePAXTime(s string) (time.Time, error)
parseString
method
#
parseString parses bytes as a NUL-terminated C-style string.
If a NUL byte is not found then the whole slice is returned as a string.
func (*parser) parseString(b []byte) string
physicalRemaining
method
#
func (sw sparseFileWriter) physicalRemaining() int64
physicalRemaining
method
#
physicalRemaining implements fileState.physicalRemaining.
func (fw regFileWriter) physicalRemaining() int64
physicalRemaining
method
#
func (sr sparseFileReader) physicalRemaining() int64
physicalRemaining
method
#
physicalRemaining implements fileState.physicalRemaining.
func (fr regFileReader) physicalRemaining() int64
prefix
method
#
func (h *headerSTAR) prefix() []byte
prefix
method
#
func (h *headerUSTAR) prefix() []byte
readFrom
method
#
readFrom populates the content of the current file by reading from r.
The bytes read must match the number of remaining bytes in the current file.
If the current file is sparse and r is an io.ReadSeeker,
then readFrom uses Seek to skip past holes defined in Header.SparseHoles,
assuming that skipped regions are all NULs.
This always reads the last byte to ensure r is the right size.
TODO(dsnet): Re-export this when adding sparse file support.
See https://golang.org/issue/22735
func (tw *Writer) readFrom(r io.Reader) (int64, error)
readGNUSparseMap0x1
function
#
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)
readGNUSparseMap1x0
function
#
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)
readOldGNUSparseMap
method
#
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)
readSpecialFile
function
#
readSpecialFile is like io.ReadAll except it returns
ErrFieldTooLong if more than maxSpecialFileSize is read.
func readSpecialFile(r io.Reader) ([]byte, error)
realSize
method
#
func (h *headerGNU) realSize() []byte
reset
method
#
reset clears the block with all zeros.
func (b *block) reset()
setFormat
method
#
setFormat writes the magic values necessary for specified format
and then updates the checksum accordingly.
func (b *block) setFormat(format Format)
size
method
#
func (h *headerV7) size() []byte
sparse
method
#
func (h *headerGNU) sparse() sparseArray
splitUSTARPath
function
#
splitUSTARPath splits a path according to USTAR prefix and suffix rules.
If the path is not splittable, then it will return ("", "", false).
func splitUSTARPath(name string) (prefix string, suffix string, ok bool)
statAtime
function
#
func statAtime(st *syscall.Stat_t) time.Time
statAtime
function
#
func statAtime(st *syscall.Stat_t) time.Time
statCtime
function
#
func statCtime(st *syscall.Stat_t) time.Time
statCtime
function
#
func statCtime(st *syscall.Stat_t) time.Time
statUnix
function
#
func statUnix(fi fs.FileInfo, h *Header, doNameLookups bool) error
templateV7Plus
method
#
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 using the provided formatters.
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
toASCII
function
#
toASCII converts the input to an ASCII C-style string.
This is a best effort conversion, so invalid characters are dropped.
func toASCII(s string) string
toGNU
method
#
func (b *block) toGNU() *headerGNU
toSTAR
method
#
func (b *block) toSTAR() *headerSTAR
toSparse
method
#
func (b *block) toSparse() sparseArray
toUSTAR
method
#
func (b *block) toUSTAR() *headerUSTAR
toV7
method
#
Convert block to any number of formats.
func (b *block) toV7() *headerV7
trailer
method
#
func (h *headerSTAR) trailer() []byte
tryReadFull
function
#
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)
typeFlag
method
#
func (h *headerV7) typeFlag() []byte
uid
method
#
func (h *headerV7) uid() []byte
userName
method
#
func (h *headerUSTAR) userName() []byte
userName
method
#
func (h *headerGNU) userName() []byte
userName
method
#
func (h *headerSTAR) userName() []byte
v7
method
#
func (h *headerUSTAR) v7() *headerV7
v7
method
#
func (h *headerSTAR) v7() *headerV7
v7
method
#
func (h *headerGNU) v7() *headerV7
validPAXRecord
function
#
validPAXRecord reports whether the key-value pair is valid where each
record is formatted as:
"%d %s=%s\n" % (size, key, value)
Keys and values should be UTF-8, but the number of bad writers out there
forces us to be a more liberal.
Thus, we only reject all keys with NUL, and only reject NULs in values
for the PAX version of the USTAR string fields.
The key must not contain an '=' character.
func validPAXRecord(k string, v string) bool
validateSparseEntries
function
#
validateSparseEntries reports whether sp is a valid sparse map.
It does not matter whether sp represents data fragments or hole fragments.
func validateSparseEntries(sp []sparseEntry, size int64) bool
version
method
#
func (h *headerUSTAR) version() []byte
version
method
#
func (h *headerSTAR) version() []byte
version
method
#
func (h *headerGNU) version() []byte
writeRawFile
method
#
writeRawFile writes a minimal file with the given name and flag type.
It uses format to encode the header format and will write data as the body.
It uses default values for all of the other fields (as BSD and GNU tar does).
func (tw *Writer) writeRawFile(name string, data string, flag byte, format Format) error
writeTo
method
#
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)