128 lines
2.3 KiB
Go
128 lines
2.3 KiB
Go
package tools
|
|
|
|
import (
|
|
"archive/tar"
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func UnGz(tarFile, dest string) error {
|
|
srcFile, err := os.Open(tarFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer srcFile.Close()
|
|
gr, err := gzip.NewReader(srcFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer gr.Close()
|
|
tr := tar.NewReader(gr)
|
|
for {
|
|
hdr, err := tr.Next()
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
} else {
|
|
return err
|
|
}
|
|
}
|
|
filename := dest + hdr.Name
|
|
file, err := createFile(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = io.Copy(file, tr)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createFile(name string) (*os.File, error) {
|
|
err := os.MkdirAll(string([]rune(name)[0:strings.LastIndex(name, "/")]), 0755)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return os.Create(name)
|
|
}
|
|
|
|
func UnGzip(tarName, xpath string) (err error) {
|
|
tarFile, err := os.Open(tarName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
err = tarFile.Close()
|
|
}()
|
|
|
|
if err := os.Mkdir(xpath, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
absPath, err := filepath.Abs(xpath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tr := tar.NewReader(tarFile)
|
|
if strings.HasSuffix(tarName, ".gz") || strings.HasSuffix(tarName, ".gzip") {
|
|
gz, err := gzip.NewReader(tarFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer gz.Close()
|
|
tr = tar.NewReader(gz)
|
|
}
|
|
|
|
// untar each segment
|
|
for {
|
|
hdr, err := tr.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// determine proper file path info
|
|
finfo := hdr.FileInfo()
|
|
fileName := hdr.Name
|
|
if filepath.IsAbs(fileName) {
|
|
fmt.Printf("removing / prefix from %s\n", fileName)
|
|
fileName, err = filepath.Rel("/", fileName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
absFileName := filepath.Join(absPath, fileName)
|
|
|
|
if finfo.Mode().IsDir() {
|
|
if err := os.MkdirAll(absFileName, 0755); err != nil {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
|
|
// create new file with original file mode
|
|
file, err := os.OpenFile(absFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, finfo.Mode().Perm())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("x %s\n", absFileName)
|
|
n, cpErr := io.Copy(file, tr)
|
|
if closeErr := file.Close(); closeErr != nil { // close file immediately
|
|
return err
|
|
}
|
|
if cpErr != nil {
|
|
return cpErr
|
|
}
|
|
if n != finfo.Size() {
|
|
return fmt.Errorf("unexpected bytes written: wrote %d, want %d", n, finfo.Size())
|
|
}
|
|
}
|
|
return nil
|
|
}
|