github.com/moby/docker@v26.1.3+incompatible/pkg/fileutils/fileutils.go (about) 1 package fileutils // import "github.com/docker/docker/pkg/fileutils" 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 ) 9 10 // CopyFile copies from src to dst until either EOF is reached 11 // on src or an error occurs. It verifies src exists and removes 12 // the dst if it exists. 13 func CopyFile(src, dst string) (int64, error) { 14 cleanSrc := filepath.Clean(src) 15 cleanDst := filepath.Clean(dst) 16 if cleanSrc == cleanDst { 17 return 0, nil 18 } 19 sf, err := os.Open(cleanSrc) 20 if err != nil { 21 return 0, err 22 } 23 defer sf.Close() 24 if err := os.Remove(cleanDst); err != nil && !os.IsNotExist(err) { 25 return 0, err 26 } 27 df, err := os.Create(cleanDst) 28 if err != nil { 29 return 0, err 30 } 31 defer df.Close() 32 return io.Copy(df, sf) 33 } 34 35 // ReadSymlinkedDirectory returns the target directory of a symlink. 36 // The target of the symbolic link may not be a file. 37 func ReadSymlinkedDirectory(path string) (realPath string, err error) { 38 if realPath, err = filepath.Abs(path); err != nil { 39 return "", fmt.Errorf("unable to get absolute path for %s: %w", path, err) 40 } 41 if realPath, err = filepath.EvalSymlinks(realPath); err != nil { 42 return "", fmt.Errorf("failed to canonicalise path for %s: %w", path, err) 43 } 44 realPathInfo, err := os.Stat(realPath) 45 if err != nil { 46 return "", fmt.Errorf("failed to stat target '%s' of '%s': %w", realPath, path, err) 47 } 48 if !realPathInfo.Mode().IsDir() { 49 return "", fmt.Errorf("canonical path points to a file '%s'", realPath) 50 } 51 return realPath, nil 52 } 53 54 // CreateIfNotExists creates a file or a directory only if it does not already exist. 55 func CreateIfNotExists(path string, isDir bool) error { 56 if _, err := os.Stat(path); err != nil { 57 if os.IsNotExist(err) { 58 if isDir { 59 return os.MkdirAll(path, 0o755) 60 } 61 if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { 62 return err 63 } 64 f, err := os.OpenFile(path, os.O_CREATE, 0o755) 65 if err != nil { 66 return err 67 } 68 f.Close() 69 } 70 } 71 return nil 72 }