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 }