Commit c0914d5d authored by Ian Lance Taylor's avatar Ian Lance Taylor

os: add SyscallConn method for os.File

Fixes #24331

Change-Id: I119c09a4259d852cdf8ea31b3e03e6f09a5f7bda
Reviewed-on: https://go-review.googlesource.com/c/155517Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 6a64efc2
......@@ -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)
}
......@@ -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
}
......@@ -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 {
......
......@@ -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 {
......
// 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
}
// 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")
}
}
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment