mirror of
https://github.com/c4milo/unpackit.git
synced 2025-09-26 19:01:11 +08:00
Added support for xz format
This commit is contained in:
BIN
fixtures/test.tar.xz
Normal file
BIN
fixtures/test.tar.xz
Normal file
Binary file not shown.
49
unzipit.go
49
unzipit.go
@@ -23,6 +23,8 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ulikunitz/xz"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -30,6 +32,7 @@ var (
|
||||
magicGZ = []byte{0x1f, 0x8b}
|
||||
magicBZIP = []byte{0x42, 0x5a}
|
||||
magicTAR = []byte{0x75, 0x73, 0x74, 0x61, 0x72} // at offset 257
|
||||
magicXZ = []byte{0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00}
|
||||
)
|
||||
|
||||
// Check whether a file has the magic number for tar, gzip, bzip2 or zip files
|
||||
@@ -37,18 +40,19 @@ var (
|
||||
// Note that this function does not advance the Reader.
|
||||
//
|
||||
// 50 4b 03 04 for pkzip format
|
||||
// 1f 8b for .gz
|
||||
// 42 5a for bzip
|
||||
// 1f 8b for .gz format
|
||||
// 42 5a for .bzip format
|
||||
// 75 73 74 61 72 at offset 257 for tar files
|
||||
// fd 37 7a 58 5a 00 for .xz format
|
||||
func magicNumber(reader *bufio.Reader, offset int) (string, error) {
|
||||
headerBytes, err := reader.Peek(offset + 5)
|
||||
headerBytes, err := reader.Peek(offset + 6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
magic := headerBytes[offset : offset+5]
|
||||
magic := headerBytes[offset : offset+6]
|
||||
|
||||
if bytes.Equal(magicTAR, magic) {
|
||||
if bytes.Equal(magicTAR, magic[0:5]) {
|
||||
return "tar", nil
|
||||
}
|
||||
|
||||
@@ -62,6 +66,10 @@ func magicNumber(reader *bufio.Reader, offset int) (string, error) {
|
||||
return "bzip", nil
|
||||
}
|
||||
|
||||
if bytes.Equal(magicXZ, magic) {
|
||||
return "xz", nil
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -70,6 +78,7 @@ func magicNumber(reader *bufio.Reader, offset int) (string, error) {
|
||||
//
|
||||
// File formats supported are:
|
||||
// - .tar.gz
|
||||
// - .tar.xz
|
||||
// - .tar.bzip2
|
||||
// - .zip
|
||||
// - .tar
|
||||
@@ -117,6 +126,11 @@ func UnpackStream(reader io.Reader, destPath string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case "xz":
|
||||
decompressingReader, err = UnxzStream(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case "bzip":
|
||||
decompressingReader, err = Bunzip2Stream(r)
|
||||
if err != nil {
|
||||
@@ -132,6 +146,9 @@ func UnpackStream(reader io.Reader, destPath string) (string, error) {
|
||||
|
||||
// Check magic number in offset 257 too see if this is also a TAR file
|
||||
ftype, err = magicNumber(decompressingReader, 257)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ftype == "tar" {
|
||||
return Untar(decompressingReader, destPath)
|
||||
}
|
||||
@@ -196,6 +213,28 @@ func GunzipStream(reader io.Reader) (*bufio.Reader, error) {
|
||||
return bufio.NewReader(decompressingReader), nil
|
||||
}
|
||||
|
||||
// Unxz decompresses a xz file and returns the decompressed stream
|
||||
func Unxz(file *os.File) (*bufio.Reader, error) {
|
||||
freader := bufio.NewReader(file)
|
||||
xzReader, err := UnxzStream(freader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bufio.NewReader(xzReader), nil
|
||||
}
|
||||
|
||||
// UnxzStream unpacks a xz stream
|
||||
func UnxzStream(reader io.Reader) (*bufio.Reader, error) {
|
||||
var decompressingReader *xz.Reader
|
||||
var err error
|
||||
if decompressingReader, err = xz.NewReader(reader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bufio.NewReader(decompressingReader), nil
|
||||
}
|
||||
|
||||
// Unzip decompresses and unarchives a ZIP archive, returning the final path or an error
|
||||
func Unzip(file *os.File, destPath string) (string, error) {
|
||||
fstat, err := file.Stat()
|
||||
|
@@ -16,6 +16,7 @@ import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/bradfitz/iter"
|
||||
)
|
||||
|
||||
@@ -53,6 +54,7 @@ func TestUnpack(t *testing.T) {
|
||||
}{
|
||||
{"./fixtures/test.tar.bzip2", 2},
|
||||
{"./fixtures/test.tar.gz", 2},
|
||||
{"./fixtures/test.tar.xz", 2},
|
||||
{"./fixtures/test.zip", 2},
|
||||
{"./fixtures/filetest.zip", 3},
|
||||
{"./fixtures/test.tar", 2},
|
||||
@@ -85,6 +87,7 @@ func TestUnpackStream(t *testing.T) {
|
||||
}{
|
||||
{"./fixtures/test.tar.bzip2", 2},
|
||||
{"./fixtures/test.tar.gz", 2},
|
||||
{"./fixtures/test.tar.xz", 2},
|
||||
{"./fixtures/test.zip", 2},
|
||||
{"./fixtures/test.tar", 2},
|
||||
{"./fixtures/cfgdrv.iso", 1},
|
||||
@@ -119,6 +122,7 @@ func TestMagicNumber(t *testing.T) {
|
||||
}{
|
||||
{"./fixtures/test.tar.bzip2", 0, "bzip"},
|
||||
{"./fixtures/test.tar.gz", 0, "gzip"},
|
||||
{"./fixtures/test.tar.xz", 0, "xz"},
|
||||
{"./fixtures/test.zip", 0, "zip"},
|
||||
{"./fixtures/test.tar", 257, "tar"},
|
||||
}
|
||||
@@ -294,11 +298,11 @@ func calcNumberOfFiles(t *testing.T, searchDir string) int {
|
||||
fileList := []string{}
|
||||
|
||||
err := filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
|
||||
if !f.IsDir() {
|
||||
fileList = append(fileList, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if !f.IsDir() {
|
||||
fileList = append(fileList, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
|
Reference in New Issue
Block a user