unix: replace blocked dup2 calls with dup3 on Android

Android O and newer blocks access to the dup2 syscall. Route calls
to Dup2 to Dup3.

Change-Id: I76c0180db260ece4840b8ebf2736fb3f8c7ff9eb
Reviewed-on: https://go-review.googlesource.com/c/sys/+/231277
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 4326a81..942a4bb 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -1633,6 +1633,15 @@
 //sys	CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
 //sys	DeleteModule(name string, flags int) (err error)
 //sys	Dup(oldfd int) (fd int, err error)
+
+func Dup2(oldfd, newfd int) error {
+	// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
+	if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
+		return Dup3(oldfd, newfd, 0)
+	}
+	return dup2(oldfd, newfd)
+}
+
 //sys	Dup3(oldfd int, newfd int, flags int) (err error)
 //sysnb	EpollCreate1(flag int) (fd int, err error)
 //sysnb	EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
diff --git a/unix/syscall_linux_386.go b/unix/syscall_linux_386.go
index a8374b6..048d18e 100644
--- a/unix/syscall_linux_386.go
+++ b/unix/syscall_linux_386.go
@@ -49,7 +49,7 @@
 
 // 64-bit file system and 32-bit uid calls
 // (386 default is 32-bit file system and 16-bit uid).
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
diff --git a/unix/syscall_linux_amd64.go b/unix/syscall_linux_amd64.go
index 8ed1d54..72efe86 100644
--- a/unix/syscall_linux_amd64.go
+++ b/unix/syscall_linux_amd64.go
@@ -6,7 +6,7 @@
 
 package unix
 
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
diff --git a/unix/syscall_linux_arm.go b/unix/syscall_linux_arm.go
index 99ae613..e1913e2 100644
--- a/unix/syscall_linux_arm.go
+++ b/unix/syscall_linux_arm.go
@@ -80,7 +80,7 @@
 
 // 64-bit file system and 32-bit uid calls
 // (16-bit uid calls are not always supported in newer kernels)
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
diff --git a/unix/syscall_linux_arm64.go b/unix/syscall_linux_arm64.go
index 84ff9fa..c6de6b9 100644
--- a/unix/syscall_linux_arm64.go
+++ b/unix/syscall_linux_arm64.go
@@ -210,9 +210,9 @@
 	return InotifyInit1(0)
 }
 
-func Dup2(oldfd int, newfd int) (err error) {
-	return Dup3(oldfd, newfd, 0)
-}
+// dup2 exists because func Dup3 in syscall_linux.go references
+// it in an unreachable path. dup2 isn't available on arm64.
+func dup2(oldfd int, newfd int) error
 
 func Pause() error {
 	_, err := ppoll(nil, 0, nil, nil)
diff --git a/unix/syscall_linux_mips64x.go b/unix/syscall_linux_mips64x.go
index af77e6e..f028747 100644
--- a/unix/syscall_linux_mips64x.go
+++ b/unix/syscall_linux_mips64x.go
@@ -7,7 +7,7 @@
 
 package unix
 
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
diff --git a/unix/syscall_linux_mipsx.go b/unix/syscall_linux_mipsx.go
index e286c6b..c113281 100644
--- a/unix/syscall_linux_mipsx.go
+++ b/unix/syscall_linux_mipsx.go
@@ -14,7 +14,7 @@
 
 func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
 
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
diff --git a/unix/syscall_linux_ppc64x.go b/unix/syscall_linux_ppc64x.go
index ca0345a..3493744 100644
--- a/unix/syscall_linux_ppc64x.go
+++ b/unix/syscall_linux_ppc64x.go
@@ -7,7 +7,7 @@
 
 package unix
 
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
diff --git a/unix/syscall_linux_riscv64.go b/unix/syscall_linux_riscv64.go
index abdabba..b0b1505 100644
--- a/unix/syscall_linux_riscv64.go
+++ b/unix/syscall_linux_riscv64.go
@@ -191,10 +191,6 @@
 	return InotifyInit1(0)
 }
 
-func Dup2(oldfd int, newfd int) (err error) {
-	return Dup3(oldfd, newfd, 0)
-}
-
 func Pause() error {
 	_, err := ppoll(nil, 0, nil, nil)
 	return err
@@ -228,3 +224,7 @@
 	}
 	return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
 }
+
+// dup2 exists because func Dup3 in syscall_linux.go references
+// it in an unreachable path. dup2 isn't available on arm64.
+func dup2(oldfd int, newfd int) error
diff --git a/unix/syscall_linux_s390x.go b/unix/syscall_linux_s390x.go
index 533e930..2363f74 100644
--- a/unix/syscall_linux_s390x.go
+++ b/unix/syscall_linux_s390x.go
@@ -10,7 +10,7 @@
 	"unsafe"
 )
 
-//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	dup2(oldfd int, newfd int) (err error)
 //sysnb	EpollCreate(size int) (fd int, err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
diff --git a/unix/syscall_linux_sparc64.go b/unix/syscall_linux_sparc64.go
index d890a22..d389f15 100644
--- a/unix/syscall_linux_sparc64.go
+++ b/unix/syscall_linux_sparc64.go
@@ -8,7 +8,7 @@
 
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
-//sys	Dup2(oldfd int, newfd int) (err error)
+//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	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
diff --git a/unix/zsyscall_linux_386.go b/unix/zsyscall_linux_386.go
index ba63af7..19ebd3f 100644
--- a/unix/zsyscall_linux_386.go
+++ b/unix/zsyscall_linux_386.go
@@ -55,7 +55,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_amd64.go b/unix/zsyscall_linux_amd64.go
index f64adef..5c56218 100644
--- a/unix/zsyscall_linux_amd64.go
+++ b/unix/zsyscall_linux_amd64.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_arm.go b/unix/zsyscall_linux_arm.go
index ac19523..dc69d99 100644
--- a/unix/zsyscall_linux_arm.go
+++ b/unix/zsyscall_linux_arm.go
@@ -234,7 +234,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_mips.go b/unix/zsyscall_linux_mips.go
index aecbbca..4918684 100644
--- a/unix/zsyscall_linux_mips.go
+++ b/unix/zsyscall_linux_mips.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_mips64.go b/unix/zsyscall_linux_mips64.go
index 424fb7f..9171d3b 100644
--- a/unix/zsyscall_linux_mips64.go
+++ b/unix/zsyscall_linux_mips64.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_mips64le.go b/unix/zsyscall_linux_mips64le.go
index 28c7239..82286f0 100644
--- a/unix/zsyscall_linux_mips64le.go
+++ b/unix/zsyscall_linux_mips64le.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_mipsle.go b/unix/zsyscall_linux_mipsle.go
index 84596b3..1592062 100644
--- a/unix/zsyscall_linux_mipsle.go
+++ b/unix/zsyscall_linux_mipsle.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_ppc64.go b/unix/zsyscall_linux_ppc64.go
index de02263..73a42e2 100644
--- a/unix/zsyscall_linux_ppc64.go
+++ b/unix/zsyscall_linux_ppc64.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_ppc64le.go b/unix/zsyscall_linux_ppc64le.go
index 888f21d..6b85595 100644
--- a/unix/zsyscall_linux_ppc64le.go
+++ b/unix/zsyscall_linux_ppc64le.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_s390x.go b/unix/zsyscall_linux_s390x.go
index 9bc353f..d7032ab 100644
--- a/unix/zsyscall_linux_s390x.go
+++ b/unix/zsyscall_linux_s390x.go
@@ -45,7 +45,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)
diff --git a/unix/zsyscall_linux_sparc64.go b/unix/zsyscall_linux_sparc64.go
index 854e816..bcbbdd9 100644
--- a/unix/zsyscall_linux_sparc64.go
+++ b/unix/zsyscall_linux_sparc64.go
@@ -72,7 +72,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (err error) {
+func dup2(oldfd int, newfd int) (err error) {
 	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	if e1 != 0 {
 		err = errnoErr(e1)