diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-08-29 18:58:06 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-08-29 18:58:06 +0900 |
| commit | c2d900ec74e03e9c782cfe7b7ce06ff62cda6601 (patch) | |
| tree | fb13320bfdc62d810aa59769e8809dc2f707919e /internal/pkg/tar.go | |
| parent | bd4f29909e0750a4660eaf48e3169777a265b0ab (diff) | |
Closes #43.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/tar.go')
| -rw-r--r-- | internal/pkg/tar.go | 226 |
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() {} |
