From 58835b7e535cc96e1c8a5d85821c1545743ca757 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Thu, 24 Dec 2020 17:50:27 +0100 Subject: [PATCH] fix: move files between different volumes (closes #1177) --- fileutils/file.go | 31 +++++++++++++++++++++++++------ http/resource.go | 2 +- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/fileutils/file.go b/fileutils/file.go index 5c0248df..6e6cd2af 100644 --- a/fileutils/file.go +++ b/fileutils/file.go @@ -9,6 +9,25 @@ import ( "github.com/spf13/afero" ) +// MoveFile moves file from src to dst. +// By default the rename filesystem system call is used. If src and dst point to different volumes +// the file copy is used as a fallback +func MoveFile(fs afero.Fs, src, dst string) error { + if fs.Rename(src, dst) == nil { + return nil + } + // fallback + err := CopyFile(fs, src, dst) + if err != nil { + _ = fs.Remove(dst) + return err + } + if err := fs.Remove(src); err != nil { + return err + } + return nil +} + // CopyFile copies a file from source to dest and returns // an error if any. func CopyFile(fs afero.Fs, source, dest string) error { @@ -39,14 +58,14 @@ func CopyFile(fs afero.Fs, source, dest string) error { return err } - // Copy the mode if the user can't - // open the file. + // Copy the mode info, err := fs.Stat(source) if err != nil { - err = fs.Chmod(dest, info.Mode()) - if err != nil { - return err - } + return err + } + err = fs.Chmod(dest, info.Mode()) + if err != nil { + return err } return nil diff --git a/http/resource.go b/http/resource.go index daeb344b..08e885f8 100644 --- a/http/resource.go +++ b/http/resource.go @@ -200,7 +200,7 @@ var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request, src = path.Clean("/" + src) dst = path.Clean("/" + dst) - return d.user.Fs.Rename(src, dst) + return fileutils.MoveFile(d.user.Fs, src, dst) default: return fmt.Errorf("unsupported action %s: %w", action, errors.ErrInvalidRequestParams) }