| package fileutils // import "github.com/docker/docker/pkg/fileutils" |
| |
| import ( |
| "fmt" |
| "io" |
| "os" |
| "path/filepath" |
| ) |
| |
| // CopyFile copies from src to dst until either EOF is reached |
| // on src or an error occurs. It verifies src exists and removes |
| // the dst if it exists. |
| func CopyFile(src, dst string) (int64, error) { |
| cleanSrc := filepath.Clean(src) |
| cleanDst := filepath.Clean(dst) |
| if cleanSrc == cleanDst { |
| return 0, nil |
| } |
| sf, err := os.Open(cleanSrc) |
| if err != nil { |
| return 0, err |
| } |
| defer sf.Close() |
| if err := os.Remove(cleanDst); err != nil && !os.IsNotExist(err) { |
| return 0, err |
| } |
| df, err := os.Create(cleanDst) |
| if err != nil { |
| return 0, err |
| } |
| defer df.Close() |
| return io.Copy(df, sf) |
| } |
| |
| // ReadSymlinkedDirectory returns the target directory of a symlink. |
| // The target of the symbolic link may not be a file. |
| func ReadSymlinkedDirectory(path string) (realPath string, err error) { |
| if realPath, err = filepath.Abs(path); err != nil { |
| return "", fmt.Errorf("unable to get absolute path for %s: %w", path, err) |
| } |
| if realPath, err = filepath.EvalSymlinks(realPath); err != nil { |
| return "", fmt.Errorf("failed to canonicalise path for %s: %w", path, err) |
| } |
| realPathInfo, err := os.Stat(realPath) |
| if err != nil { |
| return "", fmt.Errorf("failed to stat target '%s' of '%s': %w", realPath, path, err) |
| } |
| if !realPathInfo.Mode().IsDir() { |
| return "", fmt.Errorf("canonical path points to a file '%s'", realPath) |
| } |
| return realPath, nil |
| } |
| |
| // CreateIfNotExists creates a file or a directory only if it does not already exist. |
| func CreateIfNotExists(path string, isDir bool) error { |
| if _, err := os.Stat(path); err != nil { |
| if os.IsNotExist(err) { |
| if isDir { |
| return os.MkdirAll(path, 0755) |
| } |
| if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { |
| return err |
| } |
| f, err := os.OpenFile(path, os.O_CREATE, 0755) |
| if err != nil { |
| return err |
| } |
| f.Close() |
| } |
| } |
| return nil |
| } |