/
archive.go
106 lines (92 loc) · 1.73 KB
/
archive.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
package main
import (
"archive/tar"
"compress/gzip"
"io"
"os"
)
// Write archive of files and dirs to stream w
func writeArchive(paths []string, w io.Writer) error {
gz := gzip.NewWriter(w)
defer gz.Close()
tw := tar.NewWriter(gz)
defer tw.Close()
for _, path := range paths {
f, err := os.Open(path)
if err != nil {
return err
}
stat, err := f.Stat()
if err != nil {
return err
}
if stat.IsDir() {
if err := iterDir(path, tw); err != nil {
return err
}
} else {
if err := tarWrite(path, tw); err != nil {
return err
}
}
}
return nil
}
// Walk through dir getting files to archive
func iterDir(dirPath string, tw *tar.Writer) error {
dir, err := os.Open(dirPath)
if err != nil {
return err
}
defer dir.Close()
fis, err := dir.Readdir(0)
if err != nil {
return err
}
for _, fi := range fis {
curPath := dirPath + "/" + fi.Name()
if fi.IsDir() {
if err := iterDir(curPath, tw); err != nil {
return err
}
} else {
if err := tarWrite(curPath, tw); err != nil {
return err
}
}
}
return nil
}
// Add file to archive stream
func tarWrite(path string, tw *tar.Writer) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return err
}
h := new(tar.Header)
h.Name = path
h.Size = fi.Size()
h.Mode = int64(fi.Mode())
h.ModTime = fi.ModTime()
if err := tw.WriteHeader(h); err != nil {
return err
}
a, err := io.Copy(tw, file)
if fi.Size() != a {
shareLog.Printf("%s did not complete", fi.Name())
}
if err != nil {
if err == io.ErrShortWrite {
shareLog.Printf("%s wrote %d out of %d - %s", fi.Name(), a,
fi.Size(), err.Error())
} else {
return err
}
}
return nil
}