diff --git a/internal/syscallcompat/emulate.go b/internal/syscallcompat/emulate.go index 35e17c6..7fea3a8 100644 --- a/internal/syscallcompat/emulate.go +++ b/internal/syscallcompat/emulate.go @@ -11,34 +11,6 @@ import ( var chdirMutex sync.Mutex -// emulateRenameat emulates the syscall for platforms that don't have it -// in the kernel (darwin). -func emulateRenameat(olddirfd int, oldpath string, newdirfd int, newpath string) error { - chdirMutex.Lock() - defer chdirMutex.Unlock() - // Unless both paths are absolute we have to save the old working dir and - // Chdir(oldWd) back to it in the end. If we error out before the first - // chdir, Chdir(oldWd) is unneccassary but does no harm. - if !filepath.IsAbs(oldpath) || !filepath.IsAbs(newpath) { - oldWd, err := os.Getwd() - if err != nil { - return err - } - defer os.Chdir(oldWd) - } - // Make oldpath absolute - oldpath, err := dirfdAbs(olddirfd, oldpath) - if err != nil { - return err - } - // Make newpath absolute - newpath, err = dirfdAbs(newdirfd, newpath) - if err != nil { - return err - } - return syscall.Rename(oldpath, newpath) -} - // emulateUnlinkat emulates the syscall for platforms that don't have it // in the kernel (darwin). func emulateUnlinkat(dirfd int, path string, flags int) (err error) { @@ -82,24 +54,6 @@ func emulateMknodat(dirfd int, path string, mode uint32, dev int) error { return syscall.Mknod(path, mode, dev) } -// dirfdAbs transforms the dirfd-relative "path" to an absolute one. If the -// path is not already absolute, this function will change the working -// directory. The caller has to chdir back. -func dirfdAbs(dirfd int, path string) (string, error) { - if filepath.IsAbs(path) { - return path, nil - } - err := syscall.Fchdir(dirfd) - if err != nil { - return "", err - } - wd, err := os.Getwd() - if err != nil { - return "", err - } - return filepath.Join(wd, path), nil -} - // emulateFchmodat emulates the syscall for platforms that don't have it // in the kernel (darwin). func emulateFchmodat(dirfd int, path string, mode uint32, flags int) (err error) { diff --git a/internal/syscallcompat/emulate_test.go b/internal/syscallcompat/emulate_test.go index 9b1994b..7d34c0c 100644 --- a/internal/syscallcompat/emulate_test.go +++ b/internal/syscallcompat/emulate_test.go @@ -9,43 +9,6 @@ import ( "golang.org/x/sys/unix" ) -func TestEmulateRenameat(t *testing.T) { - os.Mkdir(tmpDir+"/dir1", 0700) - dir1, err := os.Open(tmpDir + "/dir1") - if err != nil { - t.Fatal(err) - } - defer dir1.Close() - os.Mkdir(tmpDir+"/dir2", 0700) - dir2, err := os.Open(tmpDir + "/dir2") - if err != nil { - t.Fatal(err) - } - defer dir2.Close() - fd, err := os.Create(tmpDir + "/dir1/f1") - if err != nil { - t.Fatal(err) - } - fd.Close() - err = emulateRenameat(int(dir1.Fd()), "f1", int(dir2.Fd()), "f2") - if err != nil { - t.Fatal(err) - } - _, err = os.Stat(tmpDir + "/dir2/f2") - if err != nil { - t.Fatal(err) - } - // Test with absolute path - err = emulateRenameat(-1, tmpDir+"/dir2/f2", -1, tmpDir+"/dir2/f1") - if err != nil { - t.Fatal(err) - } - _, err = os.Stat(tmpDir + "/dir2/f1") - if err != nil { - t.Fatal(err) - } -} - func TestEmulateUnlinkat(t *testing.T) { os.Mkdir(tmpDir+"/unlink1", 0700) dirfd, err := os.Open(tmpDir + "/unlink1") diff --git a/internal/syscallcompat/sys_common.go b/internal/syscallcompat/sys_common.go index a5b2c05..d4b2e0d 100644 --- a/internal/syscallcompat/sys_common.go +++ b/internal/syscallcompat/sys_common.go @@ -62,6 +62,11 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) return unix.Openat(dirfd, path, flags, mode) } +// Renameat wraps the Renameat syscall. +func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + return unix.Renameat(olddirfd, oldpath, newdirfd, newpath) +} + // Linkat exists both in Linux and in MacOS 10.10+. func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) { return unix.Linkat(olddirfd, oldpath, newdirfd, newpath, flags) diff --git a/internal/syscallcompat/sys_common_test.go b/internal/syscallcompat/sys_common_test.go index db6719e..3e38eb2 100644 --- a/internal/syscallcompat/sys_common_test.go +++ b/internal/syscallcompat/sys_common_test.go @@ -63,6 +63,43 @@ func TestOpenat(t *testing.T) { } } +func TestRenameat(t *testing.T) { + os.Mkdir(tmpDir+"/dir1", 0700) + dir1, err := os.Open(tmpDir + "/dir1") + if err != nil { + t.Fatal(err) + } + defer dir1.Close() + os.Mkdir(tmpDir+"/dir2", 0700) + dir2, err := os.Open(tmpDir + "/dir2") + if err != nil { + t.Fatal(err) + } + defer dir2.Close() + fd, err := os.Create(tmpDir + "/dir1/f1") + if err != nil { + t.Fatal(err) + } + fd.Close() + err = Renameat(int(dir1.Fd()), "f1", int(dir2.Fd()), "f2") + if err != nil { + t.Fatal(err) + } + _, err = os.Stat(tmpDir + "/dir2/f2") + if err != nil { + t.Fatal(err) + } + // Test with absolute path + err = Renameat(-1, tmpDir+"/dir2/f2", -1, tmpDir+"/dir2/f1") + if err != nil { + t.Fatal(err) + } + _, err = os.Stat(tmpDir + "/dir2/f1") + if err != nil { + t.Fatal(err) + } +} + func TestFchmodat(t *testing.T) { regular := "TestFchmodat_Regular" f, err := os.OpenFile(tmpDir+"/"+regular, os.O_CREATE|os.O_WRONLY, 0000) diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go index 358123c..f49e41a 100644 --- a/internal/syscallcompat/sys_darwin.go +++ b/internal/syscallcompat/sys_darwin.go @@ -72,10 +72,6 @@ func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Co return Openat(dirfd, path, flags, mode) } -func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { - return emulateRenameat(olddirfd, oldpath, newdirfd, newpath) -} - func Unlinkat(dirfd int, path string, flags int) (err error) { return emulateUnlinkat(dirfd, path, flags) } diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go index d5dc021..c58f51d 100644 --- a/internal/syscallcompat/sys_linux.go +++ b/internal/syscallcompat/sys_linux.go @@ -80,11 +80,6 @@ func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Co return Openat(dirfd, path, flags, mode) } -// Renameat wraps the Renameat syscall. -func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { - return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath) -} - // Unlinkat syscall. func Unlinkat(dirfd int, path string, flags int) (err error) { return unix.Unlinkat(dirfd, path, flags)