/
unpack.go
63 lines (59 loc) · 1.5 KB
/
unpack.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
package wio
import (
"archive/tar"
"fmt"
"io"
"os"
"path/filepath"
)
// Unpack is called in Deployment phase by pack.go.
// You should not call this.
func Unpack(dest string, data io.Reader, codec string) {
r := uncompressReader(data, codec)
tr := tar.NewReader(r)
for {
hdr, err := tr.Next()
if err == io.EOF {
break // End of archive
}
if err != nil {
panic(err)
}
switch hdr.Typeflag {
case tar.TypeDir:
writeDir(dest, hdr)
break
case tar.TypeReg:
writeFile(dest, hdr, tr)
break
default:
panic(fmt.Errorf("Unknown file type: Typeflag=%d, Name=%s", hdr.Typeflag, hdr.Name))
}
}
}
func writeDir(dest string, hdr *tar.Header) {
name := filepath.Join(dest, hdr.Name)
err := os.MkdirAll(name, 0700)
if err != nil {
panic(err)
}
}
func writeFile(dest string, hdr *tar.Header, rd io.Reader) {
name := filepath.Join(dest, hdr.Name)
if err := os.MkdirAll(filepath.Dir(name), 0700); err != nil {
panic(err)
}
// For security consideration, all unpacked files can be accessed only by the command user.
// Because, we don't know whether sensitive/confidential data is embedded in the binary.
// However, anyone can run the command since each user has her/his own cache directory.
// BTW, super users (e.g. root user) can access to unpacked files anyhow.
perm := hdr.Mode & 0700
file, err := os.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.FileMode(perm))
if err != nil {
panic(err)
}
defer file.Close()
if _, err := io.Copy(file, rd); err != nil {
panic(err)
}
}