mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
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>
This commit is contained in:
parent
6a64efc250
commit
c0914d5df3
|
@ -473,3 +473,12 @@ func (f *File) SetReadDeadline(t time.Time) error {
|
||||||
func (f *File) SetWriteDeadline(t time.Time) error {
|
func (f *File) SetWriteDeadline(t time.Time) error {
|
||||||
return f.setWriteDeadline(t)
|
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
|
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 }
|
isReadonlyError = func(err error) bool { return err == syscall.EROFS }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For TestRawConnReadWrite.
|
||||||
|
type syscallDescriptor = int
|
||||||
|
|
||||||
func checkUidGid(t *testing.T, path string, uid, gid int) {
|
func checkUidGid(t *testing.T, path string, uid, gid int) {
|
||||||
dir, err := Lstat(path)
|
dir, err := Lstat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -26,6 +26,9 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// For TestRawConnReadWrite.
|
||||||
|
type syscallDescriptor = syscall.Handle
|
||||||
|
|
||||||
func TestSameWindowsFile(t *testing.T) {
|
func TestSameWindowsFile(t *testing.T) {
|
||||||
temp, err := ioutil.TempDir("", "TestSameWindowsFile")
|
temp, err := ioutil.TempDir("", "TestSameWindowsFile")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
47
src/os/rawconn.go
Normal file
47
src/os/rawconn.go
Normal file
|
@ -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
|
||||||
|
}
|
65
src/os/rawconn_test.go
Normal file
65
src/os/rawconn_test.go
Normal file
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ type RawConn interface {
|
||||||
Write(f func(fd uintptr) (done bool)) error
|
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.
|
// access to the underlying file descriptor or handle.
|
||||||
type Conn interface {
|
type Conn interface {
|
||||||
// SyscallConn returns a raw network connection.
|
// SyscallConn returns a raw network connection.
|
||||||
|
|
Loading…
Reference in a new issue