/
pack_zip.go
142 lines (121 loc) · 2.9 KB
/
pack_zip.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package problems
import (
"archive/zip"
"github.com/LanceLRQ/deer-executor/v2/common/persistence"
"github.com/pkg/errors"
"io"
"os"
"path"
"path/filepath"
"strings"
)
func packZipFile(rootPath string, targetPath string) error {
fout, err := os.Create(targetPath)
if err != nil {
return errors.Errorf("create problem package file error: %s", err.Error())
}
defer fout.Close()
zipWriter := zip.NewWriter(fout)
defer zipWriter.Close()
err = filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = strings.TrimPrefix(path, rootPath+"/")
// 排除根目录
if header.Name == rootPath {
return nil
}
if info.IsDir() {
header.Name += "/"
} else {
header.Method = zip.Deflate
}
// 排除bin目录
if strings.HasPrefix(header.Name, "bin/") {
return nil
}
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
if !info.IsDir() {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
if err != nil {
return err
}
}
return err
})
return err
}
// PackProblemsAsZip 执行题目数据表打包操作(打包成zip版本)
func PackProblemsAsZip(options *persistence.ProblemPackageOptions) error {
// 这边没法支持所有内容的校验了,只能给config签名。
if options.DigitalSign {
if options.DigitalPEM.PublicKey == nil || options.DigitalPEM.PrivateKey == nil {
return errors.Errorf("digital sign need public key and private key")
}
}
pubkeyFileName := path.Join(options.ConfigDir, ".gpg")
signFileName := path.Join(options.ConfigDir, ".sign")
// clean meta file
if _, err := os.Stat(pubkeyFileName); os.IsExist(err) {
_ = os.Remove(pubkeyFileName)
}
if _, err := os.Stat(signFileName); os.IsExist(err) {
_ = os.Remove(signFileName)
}
defer func() {
_ = os.Remove(pubkeyFileName)
_ = os.Remove(signFileName)
}()
// Cretea Public Key
if options.DigitalSign {
gpgFile, err := os.Create(pubkeyFileName)
if err != nil {
return err
}
if _, err = gpgFile.Write(options.DigitalPEM.PublicKeyRaw); err != nil {
return err
}
_ = gpgFile.Close()
}
// Create Signature (only for configFile)
fBody, err := os.Open(options.ConfigFile)
if err != nil {
return err
}
hash, err := persistence.SHA256Streams([]io.Reader{fBody})
if err != nil {
return err
}
// GPG signature
if options.DigitalSign {
hash, err = persistence.RSA2048Sign(hash, options.DigitalPEM.PrivateKey)
if err != nil {
return err
}
}
// Write to .sign file
signFile, err := os.Create(signFileName)
if err != nil {
return err
}
if _, err = signFile.Write(hash); err != nil {
return err
}
_ = signFile.Close()
// Package Zip
err = packZipFile(options.ConfigDir, options.OutFile)
return err
}