github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/container/externalbuilder/copy.go (about)

     1  /*
     2  Copyright IBM Corp. 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  
    14  	"github.com/hyperledger/fabric/common/flogging"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  // MoveOrCopyDir attempts to copy src to dest by firstly trying to move, then copy upon failure.
    19  func MoveOrCopyDir(logger *flogging.FabricLogger, srcroot, destroot string) error {
    20  	mvErr := os.Rename(srcroot, destroot)
    21  	if mvErr == nil {
    22  		return nil
    23  	}
    24  
    25  	logger.Debugf("Failed to move %s to %s: %s, try copy instead", srcroot, destroot, mvErr)
    26  
    27  	info, err := os.Stat(srcroot)
    28  	if err != nil {
    29  		return errors.WithMessagef(err, "failed to stat dir: %s", srcroot)
    30  	}
    31  
    32  	if err = os.MkdirAll(destroot, info.Mode()); err != nil {
    33  		return errors.WithMessagef(err, "failed to make dir: %s", destroot)
    34  	}
    35  
    36  	cpErr := CopyDir(srcroot, destroot)
    37  	if cpErr == nil {
    38  		return nil
    39  	}
    40  
    41  	logger.Errorf("Failed to copy %s to %s: %s", srcroot, destroot, cpErr)
    42  
    43  	rmErr := os.RemoveAll(destroot)
    44  	if rmErr != nil {
    45  		logger.Errorf("Failed to clean targeting dir %s: %s", destroot, rmErr)
    46  	}
    47  
    48  	return errors.WithMessagef(cpErr, "failed to copy %s to %s", srcroot, destroot)
    49  }
    50  
    51  // CopyDir creates a copy of a dir
    52  func CopyDir(srcroot, destroot string) error {
    53  	return filepath.Walk(srcroot, func(path string, info os.FileInfo, err error) error {
    54  		if err != nil {
    55  			return err
    56  		}
    57  
    58  		srcsubpath, err := filepath.Rel(srcroot, path)
    59  		if err != nil {
    60  			return err
    61  		}
    62  		destpath := filepath.Join(destroot, srcsubpath)
    63  
    64  		if info.IsDir() { // its a dir, make corresponding dir in the dest
    65  			if err = os.MkdirAll(destpath, info.Mode()); err != nil {
    66  				return err
    67  			}
    68  			return nil
    69  		}
    70  
    71  		// its a file, copy to corresponding path in the dest.
    72  		// Intermediate directories are ensured to exist because parent
    73  		// node is always visited before children in `filepath.Walk`.
    74  		if err = copyFile(path, destpath); err != nil {
    75  			return err
    76  		}
    77  		return nil
    78  	})
    79  }
    80  
    81  func copyFile(srcpath, destpath string) error {
    82  	srcFile, err := os.Open(srcpath)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	defer srcFile.Close()
    87  
    88  	info, err := srcFile.Stat()
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	destFile, err := os.Create(destpath)
    94  	if err != nil {
    95  		return err
    96  	}
    97  	defer destFile.Close()
    98  
    99  	if err = os.Chmod(destFile.Name(), info.Mode()); err != nil {
   100  		return err
   101  	}
   102  
   103  	if _, err = io.Copy(destFile, srcFile); err != nil {
   104  		return err
   105  	}
   106  
   107  	return nil
   108  }