From 0f0a51f1d12bb009034a38c69aa786ba62ca41e2 Mon Sep 17 00:00:00 2001 From: Alexander Menzhinsky <amenzhinsky@gmail.com> Date: Thu, 13 Apr 2017 11:23:35 -0500 Subject: [PATCH] os: lstat oldname before renaming Fixes #19647 Change-Id: Ife4f98cf2c55ee9490843797213dae2f2647b0a3 Reviewed-on: https://go-review.googlesource.com/40577 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> --- src/os/file_unix.go | 15 ++++++++++++--- src/os/os_test.go | 12 ++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/os/file_unix.go b/src/os/file_unix.go index 86271d53e8..f790b6e910 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -20,11 +20,20 @@ func fixLongPath(path string) string { func rename(oldname, newname string) error { fi, err := Lstat(newname) if err == nil && fi.IsDir() { + // if we cannot stat oldname we should + // return that error in favor of EEXIST + fi, err = Lstat(oldname) + if err != nil { + if pErr, ok := err.(*PathError); ok { + err = pErr.Err + } + return &LinkError{"rename", oldname, newname, err} + } return &LinkError{"rename", oldname, newname, syscall.EEXIST} } - e := syscall.Rename(oldname, newname) - if e != nil { - return &LinkError{"rename", oldname, newname, e} + err = syscall.Rename(oldname, newname) + if err != nil { + return &LinkError{"rename", oldname, newname, err} } return nil } diff --git a/src/os/os_test.go b/src/os/os_test.go index 8e2cd14ddf..22777aef9f 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -886,6 +886,18 @@ func TestRenameFailed(t *testing.T) { } } +func TestRenameNotExisting(t *testing.T) { + defer chtmpdir(t)() + from, to := "doesnt-exist", "dest" + + Mkdir(to, 0777) + defer Remove(to) + + if err := Rename(from, to); !IsNotExist(err) { + t.Errorf("Rename(%q, %q) = %v; want an IsNotExist error", from, to, err) + } +} + func TestRenameToDirFailed(t *testing.T) { defer chtmpdir(t)() from, to := "renamefrom", "renameto" -- 2.30.9