github.com/levb/mattermost-server@v5.3.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 }