/
unzip.go
83 lines (76 loc) · 2.05 KB
/
unzip.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package crx3
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// UnzipTo extracts the contents of a ZIP archive specified by 'filename' to the 'basepath' directory.
// It opens the ZIP file, creates the necessary directory structure, and extracts all files.
func UnzipTo(basepath string, filename string) error {
if !isDir(basepath) {
return fmt.Errorf("%w: does not exists %s",
ErrPathNotFound, basepath)
}
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
stat, err := file.Stat()
if err != nil {
return err
}
dirname := filepath.Join(basepath,
strings.TrimSuffix(filepath.Base(filename), zipExt))
return Unzip(file, stat.Size(), dirname)
}
// Unzip extracts all files and directories from the provided ZIP archive.
// It takes an io.ReaderAt 'r', the size 'size' of the ZIP archive, and the target directory 'unpacked' for extraction.
// It iterates through the archive, creating directories and writing files as necessary.
func Unzip(r io.ReaderAt, size int64, unpacked string) error {
reader, err := zip.NewReader(r, size)
if err != nil {
return err
}
if _, err := os.Stat(unpacked); os.IsNotExist(err) {
if err := os.Mkdir(unpacked, os.ModePerm); err != nil {
return err
}
}
for _, file := range reader.File {
fpath := filepath.Join(unpacked, file.Name)
if !strings.HasPrefix(fpath, filepath.Clean(unpacked)+string(os.PathSeparator)) {
return fmt.Errorf("%s: illegal file path", fpath)
}
if file.FileInfo().IsDir() {
if err := os.MkdirAll(fpath, os.ModePerm); err != nil {
return err
}
continue
}
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
if err != nil {
return err
}
rc, err := file.Open()
if err != nil {
return err
}
if _, err = io.Copy(outFile, rc); err != nil {
return err
}
if err = outFile.Close(); err != nil {
return err
}
if err = rc.Close(); err != nil {
return err
}
}
return nil
}