瀏覽代碼

x/sys/unix: add Dup2 wrapper for arm64/ppc64

arm64 doesn't have a Dup2 syscall, instead Dup3 is supposed
to be used. Since Dup3 is linux-specific, provide a wrapper
to make writing portable code easier.

    Updates golang/go#10235

To verify it, added a testcase for Dup and Dup2.

Change-Id: I066bb60d62b2bd64d7ba0fdfbb334ce2213c78e9
Reviewed-on: https://go-review.googlesource.com/20178
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Riku Voipio <riku.voipio@linaro.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Riku Voipio 9 年之前
父節點
當前提交
9d4e42a206
共有 5 個文件被更改,包括 60 次插入0 次删除
  1. 4 0
      unix/syscall_linux_arm64.go
  2. 1 0
      unix/syscall_linux_ppc64x.go
  3. 35 0
      unix/syscall_unix_test.go
  4. 10 0
      unix/zsyscall_linux_ppc64.go
  5. 10 0
      unix/zsyscall_linux_ppc64le.go

+ 4 - 0
unix/syscall_linux_arm64.go

@@ -152,6 +152,10 @@ func InotifyInit() (fd int, err error) {
 	return InotifyInit1(0)
 }
 
+func Dup2(oldfd int, newfd int) (err error) {
+	return Dup3(oldfd, newfd, 0)
+}
+
 // TODO(dfc): constants that should be in zsysnum_linux_arm64.go, remove
 // these when the deprecated syscalls that the syscall package relies on
 // are removed.

+ 1 - 0
unix/syscall_linux_ppc64x.go

@@ -7,6 +7,7 @@
 
 package unix
 
+//sys	Dup2(oldfd int, newfd int) (err error)
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fstat(fd int, stat *Stat_t) (err error)
 //sys	Fstatfs(fd int, buf *Statfs_t) (err error)

+ 35 - 0
unix/syscall_unix_test.go

@@ -316,3 +316,38 @@ func TestSeekFailure(t *testing.T) {
 		t.Fatalf("Seek(-1, 0, 0) return error with empty message")
 	}
 }
+
+func TestDup(t *testing.T) {
+	file, err := ioutil.TempFile("", "TestDup")
+	if err != nil {
+		t.Fatalf("Tempfile failed: %v", err)
+	}
+	defer os.Remove(file.Name())
+	defer file.Close()
+	f := int(file.Fd())
+
+	newFd, err := unix.Dup(f)
+	if err != nil {
+		t.Fatalf("Dup: %v", err)
+	}
+
+	err = unix.Dup2(newFd, newFd+1)
+	if err != nil {
+		t.Fatalf("Dup2: %v", err)
+	}
+
+	b1 := []byte("Test123")
+	b2 := make([]byte, 7)
+	_, err = unix.Write(newFd+1, b1)
+	if err != nil {
+		t.Fatalf("Write to dup2 fd failed: %v", err)
+	}
+	_, err = unix.Seek(f, 0, 0)
+	_, err = unix.Read(f, b2)
+	if err != nil {
+		t.Fatalf("Read back failed: %v", err)
+	}
+	if string(b1) != string(b2) {
+		t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2))
+	}
+}

+ 10 - 0
unix/zsyscall_linux_ppc64.go

@@ -1216,6 +1216,16 @@ func Munlockall() (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Dup2(oldfd int, newfd int) (err error) {
+	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
 	if e1 != 0 {

+ 10 - 0
unix/zsyscall_linux_ppc64le.go

@@ -1216,6 +1216,16 @@ func Munlockall() (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Dup2(oldfd int, newfd int) (err error) {
+	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
 	if e1 != 0 {