github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/container/externalbuilder/copy.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package externalbuilder
     8  
     9  import (
    10  	"io"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  
    15  	"github.com/hechain20/hechain/common/flogging"
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  // CopyDir creates a copy of a dir
    20  func CopyDir(logger *flogging.FabricLogger, srcroot, destroot string) error {
    21  	err := filepath.Walk(srcroot, func(path string, info os.FileInfo, err error) error {
    22  		if err != nil {
    23  			return err
    24  		}
    25  
    26  		srcsubpath, err := filepath.Rel(srcroot, path)
    27  		if err != nil {
    28  			return err
    29  		}
    30  		destpath := filepath.Join(destroot, srcsubpath)
    31  
    32  		switch {
    33  		case info.IsDir():
    34  			return os.MkdirAll(destpath, info.Mode())
    35  		case info.Mode()&os.ModeSymlink == os.ModeSymlink:
    36  			// filepath.Walk does not follow symbolic links; we need to copy
    37  			// symbolic links as-is because some chaincode types (Node.js) rely
    38  			// on the use of symbolic links.
    39  			return copySymlink(srcroot, path, destpath)
    40  		case info.Mode().IsRegular():
    41  			// Intermediate directories are ensured to exist because parent
    42  			// node is always visited before children in `filepath.Walk`.
    43  			return copyFile(path, destpath)
    44  		default:
    45  			// It's something else that we don't support copying (device, socket, etc)
    46  			return errors.Errorf("refusing to copy unsupported file %s with mode %o", path, info.Mode())
    47  		}
    48  	})
    49  	// If an error occurred, clean up any created files.
    50  	if err != nil {
    51  		if err := os.RemoveAll(destroot); err != nil {
    52  			logger.Errorf("failed to remove destination directory %s after copy error: %s", destroot, err)
    53  		}
    54  		return errors.WithMessagef(err, "failed to copy %s to %s", srcroot, destroot)
    55  	}
    56  	return nil
    57  }
    58  
    59  func copySymlink(srcroot, srcpath, destpath string) error {
    60  	// If the symlink is absolute, then we do not want to copy it.
    61  	symlinkDest, err := os.Readlink(srcpath)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	if filepath.IsAbs(symlinkDest) {
    66  		return errors.Errorf("refusing to copy absolute symlink %s -> %s", srcpath, symlinkDest)
    67  	}
    68  
    69  	// Determine where the symlink points to. If it points outside
    70  	// of the source root, then we do not want to copy it.
    71  	symlinkDir := filepath.Dir(srcpath)
    72  	symlinkTarget := filepath.Clean(filepath.Join(symlinkDir, symlinkDest))
    73  	relativeTarget, err := filepath.Rel(srcroot, symlinkTarget)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	if relativeTargetElements := strings.Split(relativeTarget, string(os.PathSeparator)); len(relativeTargetElements) >= 1 && relativeTargetElements[0] == ".." {
    78  		return errors.Errorf("refusing to copy symlink %s -> %s pointing outside of source root", srcpath, symlinkDest)
    79  	}
    80  
    81  	return os.Symlink(symlinkDest, destpath)
    82  }
    83  
    84  func copyFile(srcpath, destpath string) error {
    85  	srcFile, err := os.Open(srcpath)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	defer srcFile.Close()
    90  
    91  	info, err := srcFile.Stat()
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	destFile, err := os.Create(destpath)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	defer destFile.Close()
   101  
   102  	if err = os.Chmod(destFile.Name(), info.Mode()); err != nil {
   103  		return err
   104  	}
   105  
   106  	if _, err = io.Copy(destFile, srcFile); err != nil {
   107  		return err
   108  	}
   109  
   110  	return nil
   111  }