aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-12-20 15:09:41 -0800
committerIan Lance Taylor <iant@golang.org>2018-12-27 16:36:34 +0000
commitc0914d5df3f12449f52e26eb0aaa58661ad92250 (patch)
tree30c007b7003fc56cd59e9a69562545c92df746e9 /src
parent6a64efc25004175e198e75191e215a7b1a08a2fa (diff)
downloadgo-c0914d5df3f12449f52e26eb0aaa58661ad92250.tar.xz
os: add SyscallConn method for os.File
Fixes #24331 Change-Id: I119c09a4259d852cdf8ea31b3e03e6f09a5f7bda Reviewed-on: https://go-review.googlesource.com/c/155517 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/os/file.go9
-rw-r--r--src/os/file_plan9.go18
-rw-r--r--src/os/os_unix_test.go3
-rw-r--r--src/os/os_windows_test.go3
-rw-r--r--src/os/rawconn.go47
-rw-r--r--src/os/rawconn_test.go65
-rw-r--r--src/syscall/net.go2
7 files changed, 146 insertions, 1 deletions
diff --git a/src/os/file.go b/src/os/file.go
index 228777c677..fdead63bfc 100644
--- a/src/os/file.go
+++ b/src/os/file.go
@@ -473,3 +473,12 @@ func (f *File) SetReadDeadline(t time.Time) error {
func (f *File) SetWriteDeadline(t time.Time) error {
return f.setWriteDeadline(t)
}
+
+// SyscallConn returns a raw file.
+// This implements the syscall.Conn interface.
+func (f *File) SyscallConn() (syscall.RawConn, error) {
+ if err := f.checkValid("SyscallConn"); err != nil {
+ return nil, err
+ }
+ return newRawConn(f)
+}
diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go
index 2c74403434..3fa12e6816 100644
--- a/src/os/file_plan9.go
+++ b/src/os/file_plan9.go
@@ -534,3 +534,21 @@ func (f *File) checkValid(op string) error {
}
return nil
}
+
+type rawConn struct{}
+
+func (c *rawConn) Control(f func(uintptr)) error {
+ return syscall.EPLAN9
+}
+
+func (c *rawConn) Read(f func(uintptr) bool) error {
+ return syscall.EPLAN9
+}
+
+func (c *rawConn) Write(f func(uintptr) bool) error {
+ return syscall.EPLAN9
+}
+
+func newRawConn(file *File) (*rawConn, error) {
+ return nil, syscall.EPLAN9
+}
diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go
index 0317f7257e..2aa930ea80 100644
--- a/src/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
@@ -22,6 +22,9 @@ func init() {
isReadonlyError = func(err error) bool { return err == syscall.EROFS }
}
+// For TestRawConnReadWrite.
+type syscallDescriptor = int
+
func checkUidGid(t *testing.T, path string, uid, gid int) {
dir, err := Lstat(path)
if err != nil {
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
index 1023b25e22..285e1eb35e 100644
--- a/src/os/os_windows_test.go
+++ b/src/os/os_windows_test.go
@@ -26,6 +26,9 @@ import (
"unsafe"
)
+// For TestRawConnReadWrite.
+type syscallDescriptor = syscall.Handle
+
func TestSameWindowsFile(t *testing.T) {
temp, err := ioutil.TempDir("", "TestSameWindowsFile")
if err != nil {
diff --git a/src/os/rawconn.go b/src/os/rawconn.go
new file mode 100644
index 0000000000..9e11cda8c9
--- /dev/null
+++ b/src/os/rawconn.go
@@ -0,0 +1,47 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !plan9
+
+package os
+
+import (
+ "runtime"
+)
+
+// rawConn implements syscall.RawConn.
+type rawConn struct {
+ file *File
+}
+
+func (c *rawConn) Control(f func(uintptr)) error {
+ if err := c.file.checkValid("SyscallConn.Control"); err != nil {
+ return err
+ }
+ err := c.file.pfd.RawControl(f)
+ runtime.KeepAlive(c.file)
+ return err
+}
+
+func (c *rawConn) Read(f func(uintptr) bool) error {
+ if err := c.file.checkValid("SyscallConn.Read"); err != nil {
+ return err
+ }
+ err := c.file.pfd.RawRead(f)
+ runtime.KeepAlive(c.file)
+ return err
+}
+
+func (c *rawConn) Write(f func(uintptr) bool) error {
+ if err := c.file.checkValid("SyscallConn.Write"); err != nil {
+ return err
+ }
+ err := c.file.pfd.RawWrite(f)
+ runtime.KeepAlive(c.file)
+ return err
+}
+
+func newRawConn(file *File) (*rawConn, error) {
+ return &rawConn{file: file}, nil
+}
diff --git a/src/os/rawconn_test.go b/src/os/rawconn_test.go
new file mode 100644
index 0000000000..820150d959
--- /dev/null
+++ b/src/os/rawconn_test.go
@@ -0,0 +1,65 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test use of raw connections.
+// +build !plan9,!nacl,!js
+
+package os_test
+
+import (
+ "os"
+ "syscall"
+ "testing"
+)
+
+func TestRawConnReadWrite(t *testing.T) {
+ t.Parallel()
+
+ r, w, err := os.Pipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+ defer w.Close()
+
+ rconn, err := r.SyscallConn()
+ if err != nil {
+ t.Fatal(err)
+ }
+ wconn, err := w.SyscallConn()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var operr error
+ err = wconn.Write(func(s uintptr) bool {
+ _, operr = syscall.Write(syscallDescriptor(s), []byte{'b'})
+ return operr != syscall.EAGAIN
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ if operr != nil {
+ t.Fatal(err)
+ }
+
+ var n int
+ buf := make([]byte, 1)
+ err = rconn.Read(func(s uintptr) bool {
+ n, operr = syscall.Read(syscallDescriptor(s), buf)
+ return operr != syscall.EAGAIN
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ if operr != nil {
+ t.Fatal(operr)
+ }
+ if n != 1 {
+ t.Errorf("read %d bytes, expected 1", n)
+ }
+ if buf[0] != 'b' {
+ t.Errorf("read %q, expected %q", buf, "b")
+ }
+}
diff --git a/src/syscall/net.go b/src/syscall/net.go
index 272d3afc38..531fa80d8f 100644
--- a/src/syscall/net.go
+++ b/src/syscall/net.go
@@ -26,7 +26,7 @@ type RawConn interface {
Write(f func(fd uintptr) (done bool)) error
}
-// Conn is implemented by some types in the net package to provide
+// Conn is implemented by some types in the net and os packages to provide
// access to the underlying file descriptor or handle.
type Conn interface {
// SyscallConn returns a raw network connection.