Documentation
¶
Overview ¶
Package tar provides utilities for creating and extracting tar archives, with optional gzip compression. Tar writes a sanitized archive of a directory tree, skipping symlinks and other non-regular, non-directory entries; use ResolveSymlinks (or the confined ResolveSymlinksRoot) to materialize symlink targets before archiving. Untar safely extracts a tar archive into a target directory, rejecting path traversal and capping the total decompressed size.
Creating an archive ¶
Archive a directory tree to a file as a gzip-compressed tarball:
f, err := os.Create("archive.tar.gz")
if err != nil {
return err
}
defer f.Close()
if _, err := tar.Tar("/path/to/dir", f); err != nil {
return err
}
Exclude entries with a filter and write a plain (non-gzipped) tar:
skipHidden := func(p string, fi os.FileInfo) bool {
return strings.HasPrefix(fi.Name(), ".")
}
_, err := tar.Tar("/path/to/dir", f,
tar.WithFilter(skipHidden),
tar.WithSkipGzip(),
)
Extracting an archive ¶
Extract a gzip-compressed tarball into a directory:
f, err := os.Open("archive.tar.gz")
if err != nil {
return err
}
defer f.Close()
if err := tar.Untar(f, "/path/to/target"); err != nil {
return err
}
Raise the size limit and tolerate symlinks in the archive:
err := tar.Untar(f, "/path/to/target", tar.WithMaxUntarSize(500<<20), // 500 MiB tar.WithSkipSymlinks(), )
Archiving with symlinks resolved ¶
By default Tar skips symlinks. For inputs where files live behind symlinks (for example, manifest trees generated by Nix), stage the source into a caller-owned directory with ResolveSymlinks first, then archive the resolved tree:
tmpDir, err := os.MkdirTemp("", "resolve-")
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)
if err := tar.ResolveSymlinks("/path/to/dir", tmpDir); err != nil {
return err
}
if _, err := tar.Tar(tmpDir, w); err != nil {
return err
}
For untrusted source trees, use ResolveSymlinksRoot to confine every symlink target inside a caller-supplied rootDir. Targets that resolve outside rootDir cause the call to fail without materializing them:
err := tar.ResolveSymlinksRoot("/path/to/root", "/path/to/root/src", tmpDir)
Index ¶
Constants ¶
const ( // DefaultMaxUntarSize defines the default (100MB) max amount of bytes that Untar will process. DefaultMaxUntarSize = 100 << (10 * 2) // UnlimitedUntarSize defines the value which disables untar size checks for maxUntarSize. UnlimitedUntarSize = -1 )
Variables ¶
This section is empty.
Functions ¶
func ResolveSymlinks ¶ added in v1.0.0
ResolveSymlinks stages the contents of srcDir into dstDir, following every symlink and copying the target's contents. Both paths must be existing directories.
Symlink cycles are detected and skipped. Non-regular, non-directory entries (devices, sockets, etc.) are skipped.
This is a staging helper intended to be paired with Tar for inputs that contain symlinks (for example, manifest trees generated by Nix where the actual files live outside the source directory).
Security: symlinks may point outside srcDir. Their targets are materialized in dstDir under the link's name. Only use with trusted input.
func ResolveSymlinksRoot ¶ added in v1.0.0
ResolveSymlinksRoot is the confined variant of ResolveSymlinks: every symlink target must resolve within rootDir. A symlink whose final resolved path is outside rootDir causes the function to fail.
srcDir must be within (or equal to) rootDir. dstDir is not required to be within rootDir.
Symlink cycles are detected and skipped. Non-regular, non-directory entries are skipped.
Note: containment is checked against the resolved absolute path, so intermediate "../" navigation within rootDir is allowed (common in Nix-style trees). Symlink resolution uses filepath.EvalSymlinks; this leaves a small TOCTOU window and should not be used to defend against an adversary with concurrent write access to the source tree.
func Tar ¶ added in v1.0.0
Tar writes a tar archive of dir to w and returns the number of bytes written.
By default, the archive is gzip-compressed; use WithSkipGzip to write a plain tar stream. Use WithFilter to exclude entries by path or FileInfo. The directory tree is walked recursively; symlinks and other non-regular, non-directory entries are silently skipped. Headers are sanitized to produce reproducible archives: uid, gid, user and group names, and all timestamps are zeroed.
func Untar ¶
Untar extracts a tar archive read from r into dir.
By default, r is expected to be gzip-compressed; use WithSkipGzip to read a plain tar stream. Extraction is capped at DefaultMaxUntarSize bytes; use WithMaxUntarSize to raise, lower, or disable the limit. Use WithFilter to skip entries by name or FileInfo during extraction. Entries with paths that escape dir are rejected. Symlinks fail extraction unless WithSkipSymlinks is set, in which case they are silently dropped.
If dir is a relative path, it cannot ascend from the current working directory. If dir exists, it must be a directory; otherwise it is created.
Types ¶
type Option ¶ added in v1.0.0
type Option func(*tarOpts)
Option configures the behavior of Tar and Untar. Options are silently ignored by operations they do not apply to.
func WithFilter ¶ added in v1.0.0
WithFilter sets a predicate called for each entry during archiving or extraction. Entries for which fn returns true are excluded. During Tar the path is the absolute filesystem path; during Untar it is the slash-separated name from the tar header.
func WithMaxUntarSize ¶
WithMaxUntarSize sets the limit size for archives being decompressed by Untar. When max is equal or less than 0 disables size checks.
func WithSkipGzip ¶ added in v0.8.0
func WithSkipGzip() Option
WithSkipGzip disables gzip compression: Tar writes a plain tar stream, and Untar reads one.
func WithSkipSymlinks ¶ added in v0.3.0
func WithSkipSymlinks() Option
WithSkipSymlinks allows for symlinks to be present in the tarball and skips them when decompressing.