diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/syscallcompat/emulate.go | 120 | ||||
| -rw-r--r-- | internal/syscallcompat/emulate_test.go | 76 | 
2 files changed, 141 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)  } diff --git a/internal/syscallcompat/emulate_test.go b/internal/syscallcompat/emulate_test.go index 35b2b40..0753a45 100644 --- a/internal/syscallcompat/emulate_test.go +++ b/internal/syscallcompat/emulate_test.go @@ -67,6 +67,15 @@ func TestEmulateOpenat(t *testing.T) {  	if rawFd < 0 {  		t.Fatalf("rawFd=%d", rawFd)  	} +	// Test with absolute path +	rawFd, err = emulateOpenat(-1, tmpDir + "/testOpenAt", 0, 0) +	if err != nil { +		t.Fatal(err) +	} +	defer syscall.Close(rawFd) +	if rawFd < 0 { +		t.Fatalf("rawFd=%d", rawFd) +	}  }  func TestEmulateRenameat(t *testing.T) { @@ -95,6 +104,15 @@ func TestEmulateRenameat(t *testing.T) {  	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) { @@ -135,6 +153,19 @@ func TestEmulateUnlinkat(t *testing.T) {  	if err == nil {  		t.Fatalf("dir not deleted!")  	} +	// Test with absolute path +	err = os.Mkdir(tmpDir + "/unlink1/d1", 0700) +	if err != nil { +		t.Fatal(err) +	} +	err = emulateUnlinkat(-1, tmpDir + "/unlink1/d1", unix.AT_REMOVEDIR) +	if err != nil { +		t.Fatal(err) +	} +	_, err = os.Stat(tmpDir + "/unlink1/d1") +	if err == nil { +		t.Fatalf("dir not deleted!") +	}  }  func TestEmulateMknodat(t *testing.T) { @@ -146,6 +177,15 @@ func TestEmulateMknodat(t *testing.T) {  	if err != nil {  		t.Fatal(err)  	} +	// Test with absolute path +	err = emulateMknodat(-1, tmpDir + "/fifo2", unix.S_IFIFO, 0) +	if err != nil { +		t.Fatal(err) +	} +	_, err = os.Stat(tmpDir + "/fifo2") +	if err != nil { +		t.Fatal(err) +	}  }  func TestEmulateFchmodat(t *testing.T) { @@ -187,6 +227,18 @@ func TestEmulateFchmodat(t *testing.T) {  	if st.Mode != 0100600 {  		t.Fatalf("Wrong mode: have %o, want %o", st.Mode, 0100600)  	} +	// Test with absolute path +	err = emulateFchmodat(-1, tmpDir + "/chmod", 0400, 0) +	if err != nil { +		t.Fatal(err) +	} +	err = syscall.Lstat(tmpDir + "/chmod", &st) +	if err != nil { +		t.Fatal(err) +	} +	if st.Mode != 0100400 { +		t.Fatalf("Wrong mode: have %o, want %o", st.Mode, 0100400) +	}  }  func TestEmulateFchownat(t *testing.T) { @@ -206,6 +258,18 @@ func TestEmulateSymlinkat(t *testing.T) {  	if st.Mode != 0120777 {  		t.Fatalf("Wrong mode, have %o, want 0120777", st.Mode)  	} +	// Test with absolute path +	err = emulateSymlinkat("/foo/bar/baz", -1, tmpDir + "/symlink2") +	if err != nil { +		t.Fatal(err) +	} +	err = syscall.Lstat(tmpDir + "/symlink2", &st) +	if err != nil { +		t.Fatal(err) +	} +	if st.Mode != 0120777 { +		t.Fatalf("Wrong mode, have %o, want 0120777", st.Mode) +	}  }  func TestEmulateMkdirat(t *testing.T) { @@ -220,4 +284,16 @@ func TestEmulateMkdirat(t *testing.T) {  	if !fi.IsDir() {  		t.Fatalf("mkdirat did not create a directory")  	} +	// Test with absolute path +	err = emulateMkdirat(-1, tmpDir + "/mkdirat2", 0100) +	if err != nil { +		t.Fatal(err) +	} +	fi, err = os.Stat(tmpDir + "/mkdirat2") +	if err != nil { +		t.Fatal(err) +	} +	if !fi.IsDir() { +		t.Fatalf("mkdirat did not create a directory") +	}  } | 
