]> Cypherpunks repositories - gostls13.git/commitdiff
os: add SyscallConn method for os.File
authorIan Lance Taylor <iant@golang.org>
Thu, 20 Dec 2018 23:09:41 +0000 (15:09 -0800)
committerIan Lance Taylor <iant@golang.org>
Thu, 27 Dec 2018 16:36:34 +0000 (16:36 +0000)
Fixes #24331

Change-Id: I119c09a4259d852cdf8ea31b3e03e6f09a5f7bda
Reviewed-on: https://go-review.googlesource.com/c/155517
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/os/file.go
src/os/file_plan9.go
src/os/os_unix_test.go
src/os/os_windows_test.go
src/os/rawconn.go [new file with mode: 0644]
src/os/rawconn_test.go [new file with mode: 0644]
src/syscall/net.go

index 228777c67772f347b47f2eaae47ac0166de8b399..fdead63bfc4cc5f52b20411716e754a24e719925 100644 (file)
@@ -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)
+}
index 2c74403434317ca953bc8ced3cc5235db9422ea7..3fa12e681667c92d451cfde146987fd894f75871 100644 (file)
@@ -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
+}
index 0317f7257ec516bfcd16d5dc75416cb83385f909..2aa930ea80dd0d966da82f5e2877602b8e571013 100644 (file)
@@ -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 {
index 1023b25e22584b60cad9e79775fa3f1984b960cd..285e1eb35e9d1606b90b2a1aaee75266a75e130c 100644 (file)
@@ -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 (file)
index 0000000..9e11cda
--- /dev/null
@@ -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 (file)
index 0000000..820150d
--- /dev/null
@@ -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")
+       }
+}
index 272d3afc38745108d91ece0f13e2067da9068aac..531fa80d8f1af1c6f685114bb01761bbdd552c60 100644 (file)
@@ -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.