github.com/rifflearning/mattermost-server@v5.11.1+incompatible/utils/file.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package utils
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  )
    13  
    14  // CopyFile will copy a file from src path to dst path.
    15  // Overwrites any existing files at dst.
    16  // Permissions are copied from file at src to the new file at dst.
    17  func CopyFile(src, dst string) (err error) {
    18  	in, err := os.Open(src)
    19  	if err != nil {
    20  		return
    21  	}
    22  	defer in.Close()
    23  
    24  	if err = os.MkdirAll(filepath.Dir(dst), os.ModePerm); err != nil {
    25  		return
    26  	}
    27  	out, err := os.Create(dst)
    28  	if err != nil {
    29  		return
    30  	}
    31  	defer func() {
    32  		if e := out.Close(); e != nil {
    33  			err = e
    34  		}
    35  	}()
    36  
    37  	_, err = io.Copy(out, in)
    38  	if err != nil {
    39  		return
    40  	}
    41  
    42  	err = out.Sync()
    43  	if err != nil {
    44  		return
    45  	}
    46  
    47  	stat, err := os.Stat(src)
    48  	if err != nil {
    49  		return
    50  	}
    51  	err = os.Chmod(dst, stat.Mode())
    52  	if err != nil {
    53  		return
    54  	}
    55  
    56  	return
    57  }
    58  
    59  // CopyDir will copy a directory and all contained files and directories.
    60  // src must exist and dst must not exist.
    61  // Permissions are preserved when possible. Symlinks are skipped.
    62  func CopyDir(src string, dst string) (err error) {
    63  	src = filepath.Clean(src)
    64  	dst = filepath.Clean(dst)
    65  
    66  	stat, err := os.Stat(src)
    67  	if err != nil {
    68  		return
    69  	}
    70  	if !stat.IsDir() {
    71  		return fmt.Errorf("source must be a directory")
    72  	}
    73  
    74  	_, err = os.Stat(dst)
    75  	if err != nil && !os.IsNotExist(err) {
    76  		return
    77  	}
    78  	if err == nil {
    79  		return fmt.Errorf("destination already exists")
    80  	}
    81  
    82  	err = os.MkdirAll(dst, stat.Mode())
    83  	if err != nil {
    84  		return
    85  	}
    86  
    87  	items, err := ioutil.ReadDir(src)
    88  	if err != nil {
    89  		return
    90  	}
    91  
    92  	for _, item := range items {
    93  		srcPath := filepath.Join(src, item.Name())
    94  		dstPath := filepath.Join(dst, item.Name())
    95  
    96  		if item.IsDir() {
    97  			err = CopyDir(srcPath, dstPath)
    98  			if err != nil {
    99  				return
   100  			}
   101  		} else {
   102  			if item.Mode()&os.ModeSymlink != 0 {
   103  				continue
   104  			}
   105  
   106  			err = CopyFile(srcPath, dstPath)
   107  			if err != nil {
   108  				return
   109  			}
   110  		}
   111  	}
   112  
   113  	return
   114  }