diff --git a/router/router_server_files.go b/router/router_server_files.go index a8ab4784..2f97cce2 100644 --- a/router/router_server_files.go +++ b/router/router_server_files.go @@ -149,6 +149,13 @@ func putServerRenameFiles(c *gin.Context) { } if err := g.Wait(); err != nil { + if errors.Is(err, os.ErrExist) { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ + "error": "Cannot move or rename file, destination already exists.", + }) + return + } + TrackedServerError(err, s).AbortWithServerError(c) return } diff --git a/server/filesystem.go b/server/filesystem.go index cc439bff..792ceed2 100644 --- a/server/filesystem.go +++ b/server/filesystem.go @@ -496,17 +496,22 @@ func (fs *Filesystem) Rename(from string, to string) error { return errors.WithStack(err) } - if f, err := os.Stat(cleanedFrom); err != nil { - return errors.WithStack(err) - } else { - d := cleanedTo - if !f.IsDir() { - d = strings.TrimSuffix(d, path.Base(cleanedTo)) - } + // If the target file or directory already exists the rename function will fail, so just + // bail out now. + if _, err := os.Stat(cleanedTo); err == nil { + return os.ErrExist + } + + if cleanedTo == fs.Path() { + return errors.New("attempting to rename into an invalid directory space") + } - // Ensure that the directory we're moving into exists correctly on the system. + d := strings.TrimSuffix(cleanedTo, path.Base(cleanedTo)) + // Ensure that the directory we're moving into exists correctly on the system. Only do this if + // we're not at the root directory level. + if d != fs.Path() { if mkerr := os.MkdirAll(d, 0644); mkerr != nil { - return errors.WithStack(mkerr) + return errors.Wrap(mkerr, "failed to create directory structure for file rename") } }