aboutsummaryrefslogtreecommitdiff
path: root/archive.go
diff options
context:
space:
mode:
Diffstat (limited to 'archive.go')
-rw-r--r--archive.go235
1 files changed, 0 insertions, 235 deletions
diff --git a/archive.go b/archive.go
deleted file mode 100644
index 76c16b8..0000000
--- a/archive.go
+++ /dev/null
@@ -1,235 +0,0 @@
-package pkgtools
-
-import (
- "archive/tar"
- "fmt"
- "io"
- "os"
- "path"
- "path/filepath"
-
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
-)
-
-type TarReader interface {
- Next() (*tar.Header, error)
- Read([]byte) (int, error)
-}
-
-const NewDirMod = 0755
-
-func tarCreateBlockDev(target string, header *tar.Header) error {
- mode := uint32(header.Mode & 07777)
- mode |= unix.S_IFBLK
- dev := unix.Mkdev(uint32(header.Devmajor), uint32(header.Devminor))
- err := unix.Mknod(target, mode, int(dev))
- return err
-}
-
-func tarCreateCharDev(target string, header *tar.Header) error {
- mode := uint32(header.Mode & 07777)
- mode |= unix.S_IFCHR
- dev := unix.Mkdev(uint32(header.Devmajor), uint32(header.Devminor))
- err := unix.Mknod(target, mode, int(dev))
- return err
-}
-
-func tarCreateDir(target string) error {
- err := os.MkdirAll(target, NewDirMod)
- return err
-}
-
-func tarCreateFifo(target string, header *tar.Header) error {
- mode := uint32(header.Mode & 07777)
- mode |= unix.S_IFIFO
- dev := unix.Mkdev(uint32(header.Devmajor), uint32(header.Devminor))
- err := unix.Mknod(target, mode, int(dev))
- return err
-}
-
-func tarCreateReg(target string, r io.Reader, header *tar.Header) error {
- f, err := os.OpenFile(
- target,
- os.O_CREATE|os.O_RDWR,
- os.FileMode(header.Mode),
- )
- if err != nil {
- // it could be an error due to writing over a running executable.
- err = os.Remove(target)
- if err != nil {
- return err
- }
-
- f, err = os.OpenFile(
- target,
- os.O_CREATE|os.O_RDWR,
- os.FileMode(header.Mode),
- )
- if err != nil {
- return err
- }
- }
- defer f.Close()
-
- // copy over contents
- if _, err := io.Copy(f, r); err != nil {
- return err
- }
- return nil
-}
-
-func tarCreateLink(root string, header *tar.Header) error {
- oldName := filepath.Join(root, header.Linkname)
- if filepath.IsAbs(header.Linkname) {
- filepath.Join(root, oldName)
- }
- newName := filepath.Join(root, header.Name)
- err := os.Link(oldName, newName)
- if err != nil {
- _ = os.Remove(newName)
- err = os.Link(oldName, newName)
- }
- return err
-}
-
-func tarCreateSymlink(root string, header *tar.Header) error {
- oldName := filepath.Join(root, header.Linkname)
- if filepath.IsAbs(header.Linkname) {
- filepath.Join(root, oldName)
- }
- newName := filepath.Join(root, header.Name)
- err := os.Symlink(oldName, newName)
- if err != nil {
- _ = os.Remove(newName)
- err = os.Symlink(oldName, newName)
- }
- return err
-}
-
-type TarFilter interface {
- FilterTar(header *tar.Header, r io.Reader) error
-}
-
-type TarFilterFunc func(
- header *tar.Header,
- r io.Reader,
-) error
-
-func (f TarFilterFunc) FilterTar(h *tar.Header, r io.Reader) error {
- return f(h, r)
-}
-
-type TarCfg struct {
- Root string
- Chown bool
- Chmod bool
- // Strict bails out when anything unexpected is encountered.
- Strict bool
-}
-
-type TarExtracter struct {
- cfg *TarCfg
-}
-
-func NewTarExtractor(cfg *TarCfg) *TarExtracter {
- return &TarExtracter{cfg}
-}
-
-func (s *TarExtracter) FilterTar(
- header *tar.Header,
- r io.Reader,
-) error {
- target := path.Join(s.cfg.Root, header.Name)
-
- if s.cfg.Strict {
- if len(header.PAXRecords) > 0 {
- return errors.Errorf(
- "%s: contains unsupported PAXRecords, bailing out",
- header.Name,
- )
- }
- if len(header.Xattrs) > 0 {
- return errors.Errorf(
- "%s: contains unsupported extended attributes, bailing out",
- header.Name,
- )
- }
- }
-
- var err error
- switch header.Typeflag {
- case tar.TypeBlock:
- err = tarCreateBlockDev(target, header)
- case tar.TypeChar:
- err = tarCreateCharDev(target, header)
- case tar.TypeFifo:
- err = tarCreateFifo(target, header)
- case tar.TypeDir:
- err = tarCreateDir(target)
- case tar.TypeReg:
- err = tarCreateReg(target, r, header)
- case tar.TypeLink:
- err = tarCreateLink(s.cfg.Root, header)
- case tar.TypeSymlink:
- err = tarCreateSymlink(s.cfg.Root, header)
- default:
- err = errors.Errorf("unhandled file type '%c'", header.Typeflag)
- }
- if err != nil {
- return errors.Wrap(err, "unpacking tar archive")
- }
-
- if s.cfg.Chown {
- if err = os.Chown(target, header.Uid, header.Gid); err != nil {
- fmt.Fprintln(os.Stderr, err)
- }
- }
- if s.cfg.Chmod {
- if err = os.Chmod(target, header.FileInfo().Mode()); err != nil {
- fmt.Fprintln(os.Stderr, err)
- }
- }
- return nil
-}
-
-func FilterTar(
- r TarReader,
- filters ...TarFilter,
-) error {
- for {
- header, err := r.Next()
- if err == io.EOF {
- break
- } else if err != nil {
- return err
- }
- if header == nil {
- continue
- }
-
- for _, f := range filters {
- // TODO: how do we dup r?
- err := f.FilterTar(header, r)
- if err != nil {
- return err
- }
- }
- }
-
- return nil
-}
-
-func ExtractTar(
- cfg *TarCfg,
- fp string,
-) error {
- f, err := os.Open(fp)
- if err != nil {
- return err
- }
- defer f.Close()
- r := tar.NewReader(f)
- err = FilterTar(r, NewTarExtractor(cfg))
- return errors.Wrap(err, "extracting tar file")
-}