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  }