forked from docker/app
/
packing.go
100 lines (95 loc) · 1.99 KB
/
packing.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
package packager
import (
"archive/tar"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/docker/app/internal"
"github.com/docker/docker/pkg/archive"
)
func tarAdd(tarout *tar.Writer, path, file string) error {
payload, err := ioutil.ReadFile(file)
if err != nil {
return err
}
h := &tar.Header{
Name: path,
Size: int64(len(payload)),
Mode: 0644,
Typeflag: tar.TypeReg,
}
err = tarout.WriteHeader(h)
if err != nil {
return err
}
_, err = tarout.Write(payload)
return err
}
// Pack packs the app as a single file
func Pack(appname string, target io.Writer) error {
tarout := tar.NewWriter(target)
for _, f := range internal.FileNames {
err := tarAdd(tarout, f, filepath.Join(appname, f))
if err != nil {
return err
}
}
// check for images
dir := "images"
_, err := os.Stat(filepath.Join(appname, dir))
if err == nil {
if err := tarout.WriteHeader(&tar.Header{
Typeflag: tar.TypeDir,
Name: dir,
Mode: 0755,
}); err != nil {
return err
}
imageDir, err := os.Open(filepath.Join(appname, dir))
if err != nil {
return err
}
defer imageDir.Close()
images, err := imageDir.Readdirnames(0)
if err != nil {
return err
}
for _, i := range images {
err = tarAdd(tarout, filepath.Join(dir, i), filepath.Join(appname, dir, i))
if err != nil {
return err
}
}
}
return tarout.Close()
}
// Unpack extracts a packed app
func Unpack(appname, targetDir string) error {
s, err := os.Stat(appname)
if err != nil {
// try appending our extension
appname = internal.DirNameFromAppName(appname)
s, err = os.Stat(appname)
}
if err != nil {
return err
}
if s.IsDir() {
return fmt.Errorf("app already extracted")
}
out := filepath.Join(targetDir, internal.AppNameFromDir(appname)+internal.AppExtension)
err = os.Mkdir(out, 0755)
if err != nil {
return err
}
f, err := os.Open(appname)
if err != nil {
return err
}
defer f.Close()
return archive.Untar(f, out, &archive.TarOptions{
NoLchown: true,
})
}