mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-17 23:16:52 +00:00
* Bump golang, golangci-lint versions and fix issues * Add -fno-stack-protector * Fix AppVeyor golangci-lint ver * Nitters * Nitters round 2
186 lines
3.7 KiB
Go
186 lines
3.7 KiB
Go
package archive
|
|
|
|
import (
|
|
"archive/zip"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/thrasher-corp/gocryptotrader/common/file"
|
|
"github.com/thrasher-corp/gocryptotrader/log"
|
|
)
|
|
|
|
const (
|
|
// ErrUnableToCloseFile message to display when file handler is unable to be closed normally
|
|
ErrUnableToCloseFile string = "Unable to close file %v %v"
|
|
)
|
|
|
|
var (
|
|
addFilesToZip func(z *zip.Writer, src string, isDir bool) error
|
|
)
|
|
|
|
func init() {
|
|
addFilesToZip = addFilesToZipWrapper
|
|
}
|
|
|
|
// UnZip extracts input zip into dest path
|
|
func UnZip(src, dest string) (fileList []string, err error) {
|
|
z, err := zip.OpenReader(src)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
for x := range z.File {
|
|
fPath := filepath.Join(dest, z.File[x].Name) //nolint // We ignore
|
|
// gosec linter above because the code below files the file traversal
|
|
// bug when extracting archives
|
|
if !strings.HasPrefix(fPath, filepath.Clean(dest)+string(os.PathSeparator)) {
|
|
err = z.Close()
|
|
if err != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, z, err)
|
|
}
|
|
err = fmt.Errorf("%s: illegal file path", fPath)
|
|
return
|
|
}
|
|
|
|
if z.File[x].FileInfo().IsDir() {
|
|
err = os.MkdirAll(fPath, os.ModePerm)
|
|
if err != nil {
|
|
return
|
|
}
|
|
continue
|
|
}
|
|
|
|
err = os.MkdirAll(filepath.Dir(fPath), file.DefaultPermissionOctal)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var outFile *os.File
|
|
outFile, err = os.OpenFile(fPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, z.File[x].Mode())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var eFile io.ReadCloser
|
|
eFile, err = z.File[x].Open()
|
|
if err != nil {
|
|
errCls := outFile.Close()
|
|
if errCls != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, outFile, errCls)
|
|
}
|
|
return
|
|
}
|
|
|
|
_, errIOCopy := io.Copy(outFile, eFile)
|
|
if errIOCopy != nil {
|
|
err = z.Close()
|
|
if err != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, z, err)
|
|
}
|
|
err = outFile.Close()
|
|
if err != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, outFile, err)
|
|
}
|
|
err = eFile.Close()
|
|
if err != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, eFile, err)
|
|
}
|
|
return fileList, errIOCopy
|
|
}
|
|
err = outFile.Close()
|
|
if err != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, outFile, err)
|
|
}
|
|
err = eFile.Close()
|
|
if err != nil {
|
|
log.Errorf(log.Global, ErrUnableToCloseFile, eFile, err)
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
fileList = append(fileList, fPath)
|
|
}
|
|
return fileList, z.Close()
|
|
}
|
|
|
|
// Zip archives requested file or folder
|
|
func Zip(src, dest string) error {
|
|
i, err := os.Stat(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f, err := os.Create(dest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
z := zip.NewWriter(f)
|
|
|
|
err = addFilesToZip(z, src, i.IsDir())
|
|
if err != nil {
|
|
z.Close()
|
|
errCls := f.Close()
|
|
if errCls != nil {
|
|
log.Errorf(log.Global, "Failed to close file handle, manual deletion required: %v", errCls)
|
|
return err
|
|
}
|
|
errRemove := os.Remove(dest)
|
|
if errRemove != nil {
|
|
log.Errorf(log.Global, "Failed to remove archive, manual deletion required: %v", errRemove)
|
|
}
|
|
return err
|
|
}
|
|
|
|
z.Close()
|
|
f.Close()
|
|
return nil
|
|
}
|
|
|
|
func addFilesToZipWrapper(z *zip.Writer, src string, isDir bool) error {
|
|
return filepath.Walk(src, func(path string, i os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h, err := zip.FileInfoHeader(i)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if isDir {
|
|
h.Name = filepath.Join(filepath.Base(src), strings.TrimPrefix(path, src))
|
|
}
|
|
|
|
if i.IsDir() {
|
|
h.Name += "/"
|
|
} else {
|
|
h.Method = zip.Deflate
|
|
}
|
|
|
|
w, err := z.CreateHeader(h)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if i.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = io.Copy(w, f)
|
|
if err != nil {
|
|
log.Errorf(log.Global, "Failed to Copy data: %v", err)
|
|
}
|
|
|
|
return f.Close()
|
|
})
|
|
}
|