tar.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package helper
  2. import (
  3. "archive/tar"
  4. "compress/gzip"
  5. "github.com/pkg/errors"
  6. "io"
  7. "os"
  8. "path/filepath"
  9. )
  10. func UnTar(dst, src string) (err error) {
  11. fr, err := os.Open(src)
  12. if err != nil {
  13. err = errors.Wrap(err, "unTar open src error")
  14. return
  15. }
  16. defer fr.Close()
  17. gr, err := gzip.NewReader(fr)
  18. if err != nil {
  19. err = errors.Wrap(err, "unTar gzip.NewReader error")
  20. return
  21. }
  22. defer gr.Close()
  23. tr := tar.NewReader(gr)
  24. for {
  25. err = func() (err error) {
  26. hdr, err := tr.Next()
  27. switch {
  28. case err == io.EOF:
  29. return
  30. case err != nil:
  31. return errors.Wrap(err, "unTar tr.Next() error")
  32. case hdr == nil:
  33. return
  34. }
  35. dstFileDir := filepath.Join(dst, hdr.Name)
  36. switch hdr.Typeflag {
  37. case tar.TypeDir:
  38. if b := ExistDir(dstFileDir); !b {
  39. if err = os.MkdirAll(dstFileDir, 0755); err != nil {
  40. return errors.Wrap(err, "unTar os.MkdirAll error")
  41. }
  42. }
  43. case tar.TypeReg:
  44. file, err := os.OpenFile(dstFileDir, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
  45. if err != nil {
  46. return errors.Wrap(err, "unTar os.OpenFile error")
  47. }
  48. defer file.Close()
  49. _, err = file.Seek(0, io.SeekEnd)
  50. if err != nil {
  51. return errors.Wrap(err, "unTar file.Truncate(0) error")
  52. }
  53. _, err = io.Copy(file, tr)
  54. if err != nil {
  55. return errors.Wrap(err, "unTar io.Copy error")
  56. }
  57. }
  58. return
  59. }()
  60. if err == io.EOF {
  61. break
  62. }
  63. }
  64. if err == io.EOF {
  65. err = nil
  66. }
  67. return
  68. }
  69. func ExistDir(dirname string) bool {
  70. fi, err := os.Stat(dirname)
  71. return (err == nil || os.IsExist(err)) && fi.IsDir()
  72. }