aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg/tar.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/pkg/tar.go')
-rw-r--r--internal/pkg/tar.go226
1 files changed, 0 insertions, 226 deletions
diff --git a/internal/pkg/tar.go b/internal/pkg/tar.go
deleted file mode 100644
index 9a8c4b76..00000000
--- a/internal/pkg/tar.go
+++ /dev/null
@@ -1,226 +0,0 @@
-package pkg
-
-import (
- "archive/tar"
- "errors"
- "fmt"
- "io"
- "io/fs"
- "os"
- "path/filepath"
-)
-
-// A tarArtifact is an [Artifact] unpacking a tarball backed by a [FileArtifact].
-type tarArtifact struct {
- // Caller-supplied backing tarball.
- f Artifact
-}
-
-var _ CuresExempt = new(tarArtifact)
-
-// tarArtifactNamed embeds tarArtifact for a [fmt.Stringer] tarball.
-type tarArtifactNamed struct {
- tarArtifact
- // Copied from tarArtifact.f.
- name string
-}
-
-var _ fmt.Stringer = new(tarArtifactNamed)
-
-// String returns the name of the underlying [Artifact] prefixed with unpack.
-func (a *tarArtifactNamed) String() string { return "unpack-" + a.name }
-
-// NewTar returns a new [Artifact] unpacking the tar stream produced by the
-// backing [Artifact]. The source [Artifact] must be a [FileArtifact].
-func NewTar(a Artifact) Artifact {
- ta := tarArtifact{a}
- if s, ok := a.(fmt.Stringer); ok {
- if name := s.String(); name != "" {
- return &tarArtifactNamed{ta, name}
- }
- }
- return &ta
-}
-
-// Kind returns the hardcoded [Kind] constant.
-func (a *tarArtifact) Kind() Kind { return KindTar }
-
-// Params is a noop.
-func (a *tarArtifact) Params(*IContext) {}
-
-func init() {
- register(KindTar, func(r *IRReader) Artifact {
- a := NewTar(r.Next())
- if _, ok := r.Finalise(); ok {
- panic(ErrUnexpectedChecksum)
- }
- return a
- })
-}
-
-// Inputs returns a slice containing the backing file.
-func (a *tarArtifact) Inputs() []Artifact {
- return []Artifact{a.f}
-}
-
-// IsExclusive returns false: decompressor and tar reader are fully sequential.
-func (a *tarArtifact) IsExclusive() bool { return false }
-
-// A DisallowedTypeflagError describes a disallowed typeflag encountered while
-// unpacking a tarball.
-type DisallowedTypeflagError byte
-
-func (e DisallowedTypeflagError) Error() string {
- return "disallowed typeflag '" + string(e) + "'"
-}
-
-// Cure cures the [Artifact], producing a directory located at work.
-func (a *tarArtifact) Cure(t *TContext) (err error) {
- var r io.ReadCloser
- if r, err = t.Open(a.f); err != nil {
- return
- }
-
- defer func() {
- closeErr := r.Close()
- if err == nil {
- err = closeErr
- }
- }()
-
- type dirTargetPerm struct {
- path string
- mode fs.FileMode
- }
- var madeDirectories []dirTargetPerm
-
- if err = os.MkdirAll(t.GetTempDir().String(), 0700); err != nil {
- return
- }
- var root *os.Root
- if root, err = os.OpenRoot(t.GetTempDir().String()); err != nil {
- return
- }
- defer func() {
- closeErr := root.Close()
- if err == nil {
- err = closeErr
- }
- }()
-
- var header *tar.Header
- tr := tar.NewReader(r)
- for header, err = tr.Next(); err == nil; header, err = tr.Next() {
- typeflag := header.Typeflag
- if typeflag == 0 {
- if len(header.Name) > 0 && header.Name[len(header.Name)-1] == '/' {
- typeflag = tar.TypeDir
- } else {
- typeflag = tar.TypeReg
- }
- }
-
- if typeflag >= '0' && typeflag <= '9' && typeflag != tar.TypeDir {
- if err = root.MkdirAll(filepath.Dir(header.Name), 0700); err != nil {
- return
- }
- }
-
- switch typeflag {
- case tar.TypeReg:
- var f *os.File
- if f, err = root.OpenFile(
- header.Name,
- os.O_CREATE|os.O_EXCL|os.O_WRONLY,
- header.FileInfo().Mode()&0500,
- ); err != nil {
- return
- }
- if _, err = io.Copy(f, tr); err != nil {
- _ = f.Close()
- return
- } else if err = f.Close(); err != nil {
- return
- }
- break
-
- case tar.TypeLink:
- if err = root.Link(
- header.Linkname,
- header.Name,
- ); err != nil {
- return
- }
- break
-
- case tar.TypeSymlink:
- if err = root.Symlink(
- header.Linkname,
- header.Name,
- ); err != nil {
- return
- }
- break
-
- case tar.TypeDir:
- madeDirectories = append(madeDirectories, dirTargetPerm{
- path: header.Name,
- mode: header.FileInfo().Mode(),
- })
- if err = root.MkdirAll(header.Name, 0700); err != nil {
- return
- }
- break
-
- case tar.TypeChar:
- t.GetMessage().Verbosef(
- "%sskipping character device %d, %d %q%s",
- t.cache.sgrWarn, header.Devmajor, header.Devminor, header.Name, t.cache.sgrRes,
- )
- continue
-
- case tar.TypeXGlobalHeader:
- continue // ignore
-
- default:
- return DisallowedTypeflagError(typeflag)
- }
- }
- if errors.Is(err, io.EOF) {
- err = nil
- }
- if err == nil {
- for _, e := range madeDirectories {
- if err = root.Chmod(e.path, e.mode&0500); err != nil {
- return
- }
- }
- } else {
- return
- }
-
- temp := t.GetTempDir()
- if err = os.Chmod(temp.String(), 0700); err != nil {
- return
- }
-
- var entries []os.DirEntry
- if entries, err = os.ReadDir(temp.String()); err != nil {
- return
- }
-
- if len(entries) == 1 && entries[0].IsDir() {
- p := temp.Append(entries[0].Name())
- if err = os.Chmod(p.String(), 0700); err != nil {
- return
- }
- err = os.Rename(p.String(), t.GetWorkDir().String())
- } else {
- err = os.Rename(temp.String(), t.GetWorkDir().String())
- }
- return
-}
-
-// CuresExempt exempts the cheap [KindTar] implementation often at the end of a
-// [FileArtifact] pipeline.
-func (*tarArtifact) CuresExempt() {}