-
Notifications
You must be signed in to change notification settings - Fork 90
/
archives.go
128 lines (105 loc) · 2.57 KB
/
archives.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package archives
import (
"archive/tar"
"bytes"
"compress/gzip"
"io"
"os"
"path/filepath"
"github.com/pkg/errors"
)
// todo, figure out why this doesn't use the mholt tgz archiver that we
// use elsewhere in kots
func ExtractTGZArchiveFromFile(tgzFile string, destDir string) error {
fileReader, err := os.Open(tgzFile)
if err != nil {
return errors.Wrap(err, "failed to open tgz file")
}
err = ExtractTGZArchiveFromReader(fileReader, destDir)
if err != nil {
return errors.Wrap(err, "failed to extract archive")
}
return nil
}
func GetFileFromAirgap(fileToGet string, archive string) ([]byte, error) {
fileReader, err := os.Open(archive)
if err != nil {
return nil, errors.Wrap(err, "failed to open file")
}
defer fileReader.Close()
gzipReader, err := gzip.NewReader(fileReader)
if err != nil {
return nil, errors.Wrap(err, "failed to get new gzip reader")
}
defer gzipReader.Close()
tarReader := tar.NewReader(gzipReader)
var fileData []byte
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return nil, errors.Wrap(err, "failed to get read archive")
}
if header.Typeflag != tar.TypeReg {
continue
}
if header.Name != fileToGet {
continue
}
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(tarReader)
if err != nil {
return nil, errors.Wrap(err, "failed to read file from tar archive")
}
fileData = buf.Bytes()
break
}
if fileData == nil {
return nil, errors.New("file not found in archive")
}
return fileData, nil
}
func ExtractTGZArchiveFromReader(tgzReader io.Reader, destDir string) error {
gzReader, err := gzip.NewReader(tgzReader)
if err != nil {
return errors.Wrap(err, "failed to get new gzip reader")
}
defer gzReader.Close()
tarReader := tar.NewReader(gzReader)
for {
hdr, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return errors.Wrap(err, "failed to read tar data")
}
if hdr.Typeflag != tar.TypeReg {
continue
}
err = func() error {
fileName := filepath.Join(destDir, hdr.Name)
filePath, _ := filepath.Split(fileName)
err := os.MkdirAll(filePath, 0755)
if err != nil {
return errors.Wrapf(err, "failed to create directory %q", filePath)
}
fileWriter, err := os.Create(fileName)
if err != nil {
return errors.Wrapf(err, "failed to create file %q", hdr.Name)
}
defer fileWriter.Close()
_, err = io.Copy(fileWriter, tarReader)
if err != nil {
return errors.Wrapf(err, "failed to write file %q", hdr.Name)
}
return nil
}()
if err != nil {
return err
}
}
return nil
}