github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/core/container/util/writer.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "archive/tar" 21 "bufio" 22 "fmt" 23 "io" 24 "os" 25 "path/filepath" 26 "strings" 27 "time" 28 29 "github.com/hyperledger/fabric/common/flogging" 30 ) 31 32 var vmLogger = flogging.MustGetLogger("container") 33 34 // These filetypes are excluded while creating the tar package sent to Docker 35 // Generated .class and other temporary files can be excluded 36 var javaExcludeFileTypes = map[string]bool{ 37 ".class": true, 38 } 39 40 func WriteFolderToTarPackage(tw *tar.Writer, srcPath string, excludeDir string, includeFileTypeMap map[string]bool, excludeFileTypeMap map[string]bool) error { 41 rootDirectory := srcPath 42 vmLogger.Infof("rootDirectory = %s", rootDirectory) 43 44 //append "/" if necessary 45 if excludeDir != "" && strings.LastIndex(excludeDir, "/") < len(excludeDir)-1 { 46 excludeDir = excludeDir + "/" 47 } 48 49 rootDirLen := len(rootDirectory) 50 walkFn := func(path string, info os.FileInfo, err error) error { 51 52 // If path includes .git, ignore 53 if strings.Contains(path, ".git") { 54 return nil 55 } 56 57 if info.Mode().IsDir() { 58 return nil 59 } 60 61 //exclude any files with excludeDir prefix. They should already be in the tar 62 if excludeDir != "" && strings.Index(path, excludeDir) == rootDirLen+1 { 63 //1 for "/" 64 return nil 65 } 66 // Because of scoping we can reference the external rootDirectory variable 67 if len(path[rootDirLen:]) == 0 { 68 return nil 69 } 70 ext := filepath.Ext(path) 71 72 if includeFileTypeMap != nil { 73 // we only want 'fileTypes' source files at this point 74 if _, ok := includeFileTypeMap[ext]; ok != true { 75 return nil 76 } 77 } 78 79 //exclude the given file types 80 if excludeFileTypeMap != nil { 81 if exclude, ok := excludeFileTypeMap[ext]; ok && exclude { 82 return nil 83 } 84 } 85 86 newPath := fmt.Sprintf("src%s", path[rootDirLen:]) 87 //newPath := path[len(rootDirectory):] 88 89 err = WriteFileToPackage(path, newPath, tw) 90 if err != nil { 91 return fmt.Errorf("Error writing file to package: %s", err) 92 } 93 return nil 94 } 95 96 if err := filepath.Walk(rootDirectory, walkFn); err != nil { 97 vmLogger.Infof("Error walking rootDirectory: %s", err) 98 return err 99 } 100 return nil 101 } 102 103 //Package Java project to tar file from the source path 104 func WriteJavaProjectToPackage(tw *tar.Writer, srcPath string) error { 105 106 vmLogger.Debugf("Packaging Java project from path %s", srcPath) 107 108 if err := WriteFolderToTarPackage(tw, srcPath, "", nil, javaExcludeFileTypes); err != nil { 109 110 vmLogger.Errorf("Error writing folder to tar package %s", err) 111 return err 112 } 113 // Write the tar file out 114 if err := tw.Close(); err != nil { 115 return err 116 } 117 return nil 118 119 } 120 121 //WriteFileToPackage writes a file to the tarball 122 func WriteFileToPackage(localpath string, packagepath string, tw *tar.Writer) error { 123 fd, err := os.Open(localpath) 124 if err != nil { 125 return fmt.Errorf("%s: %s", localpath, err) 126 } 127 defer fd.Close() 128 129 is := bufio.NewReader(fd) 130 return WriteStreamToPackage(is, localpath, packagepath, tw) 131 132 } 133 134 //WriteStreamToPackage writes bytes (from a file reader) to the tarball 135 func WriteStreamToPackage(is io.Reader, localpath string, packagepath string, tw *tar.Writer) error { 136 info, err := os.Stat(localpath) 137 if err != nil { 138 return fmt.Errorf("%s: %s", localpath, err) 139 } 140 header, err := tar.FileInfoHeader(info, localpath) 141 if err != nil { 142 return fmt.Errorf("Error getting FileInfoHeader: %s", err) 143 } 144 145 //Let's take the variance out of the tar, make headers identical by using zero time 146 oldname := header.Name 147 var zeroTime time.Time 148 header.AccessTime = zeroTime 149 header.ModTime = zeroTime 150 header.ChangeTime = zeroTime 151 header.Name = packagepath 152 header.Mode = 0100644 153 154 if err = tw.WriteHeader(header); err != nil { 155 return fmt.Errorf("Error write header for (path: %s, oldname:%s,newname:%s,sz:%d) : %s", localpath, oldname, packagepath, header.Size, err) 156 } 157 if _, err := io.Copy(tw, is); err != nil { 158 return fmt.Errorf("Error copy (path: %s, oldname:%s,newname:%s,sz:%d) : %s", localpath, oldname, packagepath, header.Size, err) 159 } 160 161 return nil 162 } 163 164 func WriteBytesToPackage(name string, payload []byte, tw *tar.Writer) error { 165 //Make headers identical by using zero time 166 var zeroTime time.Time 167 tw.WriteHeader(&tar.Header{Name: name, Size: int64(len(payload)), ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) 168 tw.Write(payload) 169 170 return nil 171 }