diff --git a/internal/util/decompressor.go b/internal/util/decompressor.go index 9480922..9ce0466 100644 --- a/internal/util/decompressor.go +++ b/internal/util/decompressor.go @@ -20,6 +20,7 @@ import ( "archive/tar" "archive/zip" "bytes" + "compress/bzip2" "compress/gzip" "fmt" "github.com/bodgit/sevenzip" @@ -190,6 +191,77 @@ loop: return nil } +type Bzip2TarDecompressor struct { + src string +} + +func (b *Bzip2TarDecompressor) Decompress(dest string) error { + file, err := os.Open(b.src) + if err != nil { + return err + } + defer file.Close() + + bzr := bzip2.NewReader(file) + tr := tar.NewReader(bzr) + + var symlinks []symlink + +loop: + for { + header, err := tr.Next() + switch { + case err == io.EOF: + break loop + case err != nil: + return err + case header == nil: + continue + } + + parts := strings.Split(header.Name, "/") + if len(parts) > 1 { + parts = parts[1:] + } + fname := strings.Join(parts, "/") + target := filepath.Join(dest, fname) + + switch header.Typeflag { + case tar.TypeDir: + if _, err := os.Stat(target); err != nil { + if err := os.MkdirAll(target, 0755); err != nil { + return err + } + } + case tar.TypeReg: + _ = os.MkdirAll(filepath.Dir(target), 0755) + f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) + if err != nil { + return err + } + if _, err := io.Copy(f, tr); err != nil { + return err + } + f.Close() + case tar.TypeSymlink: + symlinks = append(symlinks, symlink{header.Linkname, target}) + } + } + + for _, s := range symlinks { + dir := filepath.Dir(s.newname) + if _, err := os.Stat(dir); os.IsNotExist(err) { + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + } + if err = os.Symlink(s.oldname, s.newname); err != nil { + return err + } + } + return nil +} + type ZipDecompressor struct { src string } @@ -430,6 +502,11 @@ func NewDecompressor(src string) Decompressor { src: src, } } + if strings.HasSuffix(filename, ".tar.bz2") { + return &Bzip2TarDecompressor{ + src: src, + } + } if strings.HasSuffix(filename, ".zip") { return &ZipDecompressor{ src: src,