github.com/qxnw/lib4go@v0.0.0-20180426074627-c80c7e84b925/archiver/targz.go (about) 1 package archiver 2 3 import ( 4 "compress/gzip" 5 "fmt" 6 "io" 7 "os" 8 "strings" 9 ) 10 11 // TarGz is for TarGz format 12 var TarGz tarGzFormat 13 14 func init() { 15 RegisterFormat("TarGz", TarGz) 16 } 17 18 type tarGzFormat struct{} 19 20 func (tarGzFormat) Match(filename string) bool { 21 return strings.HasSuffix(strings.ToLower(filename), ".tar.gz") || 22 strings.HasSuffix(strings.ToLower(filename), ".tgz") || 23 isTarGz(filename) 24 } 25 26 // isTarGz checks the file has the gzip compressed Tar format header by reading 27 // its beginning block. 28 func isTarGz(targzPath string) bool { 29 f, err := os.Open(targzPath) 30 if err != nil { 31 return false 32 } 33 defer f.Close() 34 35 gzr, err := gzip.NewReader(f) 36 if err != nil { 37 return false 38 } 39 defer gzr.Close() 40 41 buf := make([]byte, tarBlockSize) 42 n, err := gzr.Read(buf) 43 if err != nil || n < tarBlockSize { 44 return false 45 } 46 47 return hasTarHeader(buf) 48 } 49 50 // Write outputs a .tar.gz file to a Writer containing 51 // the contents of files listed in filePaths. It works 52 // the same way Tar does, but with gzip compression. 53 func (tarGzFormat) Write(output io.Writer, filePaths []string) error { 54 return writeTarGz(filePaths, output, "") 55 } 56 57 // Make creates a .tar.gz file at targzPath containing 58 // the contents of files listed in filePaths. It works 59 // the same way Tar does, but with gzip compression. 60 func (tarGzFormat) Make(targzPath string, filePaths []string) error { 61 out, err := os.Create(targzPath) 62 if err != nil { 63 return fmt.Errorf("error creating %s: %v", targzPath, err) 64 } 65 defer out.Close() 66 67 return writeTarGz(filePaths, out, targzPath) 68 } 69 70 func writeTarGz(filePaths []string, output io.Writer, dest string) error { 71 gzw := gzip.NewWriter(output) 72 defer gzw.Close() 73 74 return writeTar(filePaths, gzw, dest) 75 } 76 77 // Read untars a .tar.gz file read from a Reader and decompresses 78 // the contents into destination. 79 func (tarGzFormat) Read(input io.Reader, destination string) error { 80 gzr, err := gzip.NewReader(input) 81 if err != nil { 82 return fmt.Errorf("error decompressing: %v", err) 83 } 84 defer gzr.Close() 85 86 return Tar.Read(gzr, destination) 87 } 88 89 // Open untars source and decompresses the contents into destination. 90 func (tarGzFormat) Open(source, destination string) error { 91 f, err := os.Open(source) 92 if err != nil { 93 return fmt.Errorf("%s: failed to open archive: %v", source, err) 94 } 95 defer f.Close() 96 97 return TarGz.Read(f, destination) 98 }