github.com/LanceLRQ/deer-common@v0.0.9-0.20210319081233-e8222ac018a8/persistence/problems/pack_zip.go (about) 1 package problems 2 3 import ( 4 "archive/zip" 5 "github.com/LanceLRQ/deer-common/persistence" 6 "github.com/pkg/errors" 7 "io" 8 "os" 9 "path" 10 "path/filepath" 11 "strings" 12 ) 13 14 func packZipFile(rootPath string, targetPath string) error { 15 fout, err := os.Create(targetPath) 16 if err != nil { 17 return errors.Errorf("create problem package file error: %s", err.Error()) 18 } 19 defer fout.Close() 20 21 zipWriter := zip.NewWriter(fout) 22 defer zipWriter.Close() 23 24 err = filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { 25 if err != nil { 26 return err 27 } 28 29 header, err := zip.FileInfoHeader(info) 30 if err != nil { 31 return err 32 } 33 34 header.Name = strings.TrimPrefix(path, rootPath+"/") 35 36 // 排除根目录 37 if header.Name == rootPath { 38 return nil 39 } 40 if info.IsDir() { 41 header.Name += "/" 42 } else { 43 header.Method = zip.Deflate 44 } 45 // 排除bin目录 46 if strings.HasPrefix(header.Name, "bin/") { 47 return nil 48 } 49 50 writer, err := zipWriter.CreateHeader(header) 51 if err != nil { 52 return err 53 } 54 55 if !info.IsDir() { 56 file, err := os.Open(path) 57 if err != nil { 58 return err 59 } 60 defer file.Close() 61 _, err = io.Copy(writer, file) 62 } 63 return err 64 }) 65 66 return err 67 } 68 69 // 执行题目数据表打包操作(打包成zip版本) 70 func PackProblemsAsZip(options *persistence.ProblemPackageOptions) error { 71 // 这边没法支持所有内容的校验了,只能给config签名。 72 if options.DigitalSign { 73 if options.DigitalPEM.PublicKey == nil || options.DigitalPEM.PrivateKey == nil { 74 return errors.Errorf("digital sign need public key and private key") 75 } 76 } 77 78 pubkeyFileName := path.Join(options.ConfigDir, ".gpg") 79 signFileName := path.Join(options.ConfigDir, ".sign") 80 81 // clean meta file 82 if _, err := os.Stat(pubkeyFileName); os.IsExist(err) { 83 _ = os.Remove(pubkeyFileName) 84 } 85 if _, err := os.Stat(signFileName); os.IsExist(err) { 86 _ = os.Remove(signFileName) 87 } 88 89 defer func() { 90 _ = os.Remove(pubkeyFileName) 91 _ = os.Remove(signFileName) 92 }() 93 94 // Cretea Public Key 95 if options.DigitalSign { 96 gpgFile, err := os.Create(pubkeyFileName) 97 if err != nil { 98 return err 99 } 100 if _, err = gpgFile.Write(options.DigitalPEM.PublicKeyRaw); err != nil { 101 return err 102 } 103 _ = gpgFile.Close() 104 } 105 106 // Create Signature (only for configFile) 107 fBody, err := os.Open(options.ConfigFile) 108 if err != nil { 109 return err 110 } 111 112 hash, err := persistence.SHA256Streams([]io.Reader{fBody}) 113 114 // GPG signature 115 if options.DigitalSign { 116 hash, err = persistence.RSA2048Sign(hash, options.DigitalPEM.PrivateKey) 117 if err != nil { 118 return err 119 } 120 } 121 122 // Write to .sign file 123 signFile, err := os.Create(signFileName) 124 if err != nil { 125 return err 126 } 127 if _, err = signFile.Write(hash); err != nil { 128 return err 129 } 130 _ = signFile.Close() 131 132 // Package Zip 133 err = packZipFile(options.ConfigDir, options.OutFile) 134 135 return err 136 }