diff options
author | Sebastian Lackner | 2017-11-30 21:13:46 +0100 |
---|---|---|
committer | rfjakob | 2017-12-01 09:41:52 +0100 |
commit | f30522a0c14218ad236831d1c229968ea46ec8aa (patch) | |
tree | 97e0008ca9d302b5ee5f65800b006da5fd169fb0 /internal/syscallcompat/emulate.go | |
parent | 9bcde0c09e96e17ed7092aa5fa5f6bfc89372a8d (diff) |
syscallcompat: Fix syscall emulation for absolute paths
For absolute paths, the file descriptor should be ignored. In such a case
there is also no need to hold the lock or change the working directory.
Diffstat (limited to 'internal/syscallcompat/emulate.go')
-rw-r--r-- | internal/syscallcompat/emulate.go | 120 |
1 files changed, 65 insertions, 55 deletions
diff --git a/internal/syscallcompat/emulate.go b/internal/syscallcompat/emulate.go index 3af45f8..0aca28e 100644 --- a/internal/syscallcompat/emulate.go +++ b/internal/syscallcompat/emulate.go @@ -64,18 +64,20 @@ func emulateRenameat(olddirfd int, oldpath string, newdirfd int, newpath string) // 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) { - chdirMutex.Lock() - defer chdirMutex.Unlock() - cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) - if err != nil { - return err - } - defer syscall.Close(cwd) - err = syscall.Fchdir(dirfd) - if err != nil { - return err + if !filepath.IsAbs(path) { + chdirMutex.Lock() + defer chdirMutex.Unlock() + cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) + if err != nil { + return err + } + defer syscall.Close(cwd) + err = syscall.Fchdir(dirfd) + if err != nil { + return err + } + defer syscall.Fchdir(cwd) } - defer syscall.Fchdir(cwd) if (flags & unix.AT_REMOVEDIR) != 0 { return syscall.Rmdir(path) } else { @@ -123,18 +125,20 @@ func dirfdAbs(dirfd int, path string) (string, error) { // 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) { - chdirMutex.Lock() - defer chdirMutex.Unlock() - cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) - if err != nil { - return err - } - defer syscall.Close(cwd) - err = syscall.Fchdir(dirfd) - if err != nil { - return err + if !filepath.IsAbs(path) { + chdirMutex.Lock() + defer chdirMutex.Unlock() + cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) + if err != nil { + return err + } + defer syscall.Close(cwd) + err = syscall.Fchdir(dirfd) + if err != nil { + return err + } + defer syscall.Fchdir(cwd) } - defer syscall.Fchdir(cwd) // We also don't have Lchmod, so emulate it (poorly). if flags&unix.AT_SYMLINK_NOFOLLOW != 0 { fi, err := os.Lstat(path) @@ -151,53 +155,59 @@ func emulateFchmodat(dirfd int, path string, mode uint32, flags int) (err error) // emulateFchownat emulates the syscall for platforms that don't have it // in the kernel (darwin). func emulateFchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - chdirMutex.Lock() - defer chdirMutex.Unlock() - cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) - if err != nil { - return err - } - defer syscall.Close(cwd) - err = syscall.Fchdir(dirfd) - if err != nil { - return err + if !filepath.IsAbs(path) { + chdirMutex.Lock() + defer chdirMutex.Unlock() + cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) + if err != nil { + return err + } + defer syscall.Close(cwd) + err = syscall.Fchdir(dirfd) + if err != nil { + return err + } + defer syscall.Fchdir(cwd) } - defer syscall.Fchdir(cwd) return syscall.Lchown(path, uid, gid) } // emulateSymlinkat emulates the syscall for platforms that don't have it // in the kernel (darwin). func emulateSymlinkat(oldpath string, newdirfd int, newpath string) (err error) { - chdirMutex.Lock() - defer chdirMutex.Unlock() - cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) - if err != nil { - return err - } - defer syscall.Close(cwd) - err = syscall.Fchdir(newdirfd) - if err != nil { - return err + if !filepath.IsAbs(newpath) { + chdirMutex.Lock() + defer chdirMutex.Unlock() + cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) + if err != nil { + return err + } + defer syscall.Close(cwd) + err = syscall.Fchdir(newdirfd) + if err != nil { + return err + } + defer syscall.Fchdir(cwd) } - defer syscall.Fchdir(cwd) return syscall.Symlink(oldpath, newpath) } // emulateMkdirat emulates the syscall for platforms that don't have it // in the kernel (darwin). func emulateMkdirat(dirfd int, path string, mode uint32) (err error) { - chdirMutex.Lock() - defer chdirMutex.Unlock() - cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) - if err != nil { - return err - } - defer syscall.Close(cwd) - err = syscall.Fchdir(dirfd) - if err != nil { - return err + if !filepath.IsAbs(path) { + chdirMutex.Lock() + defer chdirMutex.Unlock() + cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) + if err != nil { + return err + } + defer syscall.Close(cwd) + err = syscall.Fchdir(dirfd) + if err != nil { + return err + } + defer syscall.Fchdir(cwd) } - defer syscall.Fchdir(cwd) return syscall.Mkdir(path, mode) } |