wasi: support building internal/sysfs with TinyGo (#2160)

Signed-off-by: gram <git@orsinium.dev>
Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
Co-authored-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
This commit is contained in:
Gram
2024-03-28 11:05:24 +01:00
committed by GitHub
parent c20cade078
commit 771a1e971a
7 changed files with 100 additions and 54 deletions

View File

@@ -86,12 +86,6 @@ func (d *dirFS) Readlink(path string) (string, experimentalsys.Errno) {
return platform.ToPosixPath(dst), 0
}
// Link implements the same method as documented on sys.FS
func (d *dirFS) Link(oldName, newName string) experimentalsys.Errno {
err := os.Link(d.join(oldName), d.join(newName))
return experimentalsys.UnwrapOSError(err)
}
// Rmdir implements the same method as documented on sys.FS
func (d *dirFS) Rmdir(path string) experimentalsys.Errno {
return rmdir(d.join(path))

View File

@@ -0,0 +1,15 @@
//go:build !tinygo
package sysfs
import (
"os"
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
)
// Link implements the same method as documented on sys.FS
func (d *dirFS) Link(oldName, newName string) experimentalsys.Errno {
err := os.Link(d.join(oldName), d.join(newName))
return experimentalsys.UnwrapOSError(err)
}

View File

@@ -0,0 +1,12 @@
//go:build tinygo
package sysfs
import (
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
)
// Link implements the same method as documented on sys.FS
func (d *dirFS) Link(oldName, newName string) experimentalsys.Errno {
return experimentalsys.ENOSYS
}

View File

@@ -58,25 +58,6 @@ func newDefaultTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock {
return &tcpListenerFile{tl: tl}
}
// Accept implements the same method as documented on socketapi.TCPSock
func (f *tcpListenerFile) Accept() (socketapi.TCPConn, experimentalsys.Errno) {
// Ensure we have an incoming connection, otherwise return immediately.
if f.nonblock {
if ready, errno := _pollSock(f.tl, fsapi.POLLIN, 0); !ready || errno != 0 {
return nil, experimentalsys.EAGAIN
}
}
// Accept normally blocks goroutines, but we
// made sure that we have an incoming connection,
// so we should be safe.
if conn, err := f.tl.Accept(); err != nil {
return nil, experimentalsys.UnwrapOSError(err)
} else {
return newTcpConn(conn.(*net.TCPConn)), 0
}
}
// Close implements the same method as documented on experimentalsys.File
func (f *tcpListenerFile) Close() experimentalsys.Errno {
if !f.closed {
@@ -90,15 +71,6 @@ func (f *tcpListenerFile) Addr() *net.TCPAddr {
return f.tl.Addr().(*net.TCPAddr)
}
// SetNonblock implements the same method as documented on fsapi.File
func (f *tcpListenerFile) SetNonblock(enabled bool) (errno experimentalsys.Errno) {
f.nonblock = enabled
_, errno = syscallConnControl(f.tl, func(fd uintptr) (int, experimentalsys.Errno) {
return 0, setNonblockSocket(fd, enabled)
})
return
}
// IsNonblock implements the same method as documented on fsapi.File
func (f *tcpListenerFile) IsNonblock() bool {
return f.nonblock
@@ -182,23 +154,6 @@ func (f *tcpConnFile) Recvfrom(p []byte, flags int) (n int, errno experimentalsy
})
}
// Shutdown implements the same method as documented on experimentalsys.Conn
func (f *tcpConnFile) Shutdown(how int) experimentalsys.Errno {
// FIXME: can userland shutdown listeners?
var err error
switch how {
case socketapi.SHUT_RD:
err = f.tc.CloseRead()
case socketapi.SHUT_WR:
err = f.tc.CloseWrite()
case socketapi.SHUT_RDWR:
return f.close()
default:
return experimentalsys.EINVAL
}
return experimentalsys.UnwrapOSError(err)
}
// Close implements the same method as documented on experimentalsys.File
func (f *tcpConnFile) Close() experimentalsys.Errno {
return f.close()

View File

@@ -1,13 +1,61 @@
//go:build linux || darwin || windows
//go:build (linux || darwin || windows) && !tinygo
package sysfs
import (
"net"
"syscall"
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
"github.com/tetratelabs/wazero/internal/fsapi"
socketapi "github.com/tetratelabs/wazero/internal/sock"
)
// Accept implements the same method as documented on socketapi.TCPSock
func (f *tcpListenerFile) Accept() (socketapi.TCPConn, experimentalsys.Errno) {
// Ensure we have an incoming connection, otherwise return immediately.
if f.nonblock {
if ready, errno := _pollSock(f.tl, fsapi.POLLIN, 0); !ready || errno != 0 {
return nil, experimentalsys.EAGAIN
}
}
// Accept normally blocks goroutines, but we
// made sure that we have an incoming connection,
// so we should be safe.
if conn, err := f.tl.Accept(); err != nil {
return nil, experimentalsys.UnwrapOSError(err)
} else {
return newTcpConn(conn.(*net.TCPConn)), 0
}
}
// SetNonblock implements the same method as documented on fsapi.File
func (f *tcpListenerFile) SetNonblock(enabled bool) (errno experimentalsys.Errno) {
f.nonblock = enabled
_, errno = syscallConnControl(f.tl, func(fd uintptr) (int, experimentalsys.Errno) {
return 0, setNonblockSocket(fd, enabled)
})
return
}
// Shutdown implements the same method as documented on experimentalsys.Conn
func (f *tcpConnFile) Shutdown(how int) experimentalsys.Errno {
// FIXME: can userland shutdown listeners?
var err error
switch how {
case socketapi.SHUT_RD:
err = f.tc.CloseRead()
case socketapi.SHUT_WR:
err = f.tc.CloseWrite()
case socketapi.SHUT_RDWR:
return f.close()
default:
return experimentalsys.EINVAL
}
return experimentalsys.UnwrapOSError(err)
}
// syscallConnControl extracts a syscall.RawConn from the given syscall.Conn and applies
// the given fn to a file descriptor, returning an integer or a nonzero syscall.Errno on failure.
//

View File

@@ -1,4 +1,4 @@
//go:build linux || darwin
//go:build (linux || darwin) && !tinygo
package sysfs

View File

@@ -1,4 +1,4 @@
//go:build !linux && !darwin && !windows
//go:build (!linux && !darwin && !windows) || tinygo
package sysfs
@@ -57,3 +57,25 @@ func recvfrom(fd uintptr, buf []byte, flags int32) (n int, errno sys.Errno) {
func syscallConnControl(conn syscall.Conn, fn func(fd uintptr) (int, experimentalsys.Errno)) (n int, errno sys.Errno) {
return -1, sys.ENOTSUP
}
// Accept implements the same method as documented on socketapi.TCPSock
func (f *tcpListenerFile) Accept() (socketapi.TCPConn, experimentalsys.Errno) {
return nil, experimentalsys.ENOSYS
}
// Shutdown implements the same method as documented on experimentalsys.Conn
func (f *tcpConnFile) Shutdown(how int) experimentalsys.Errno {
// FIXME: can userland shutdown listeners?
var err error
switch how {
case socketapi.SHUT_RD:
err = f.tc.Close()
case socketapi.SHUT_WR:
err = f.tc.Close()
case socketapi.SHUT_RDWR:
return f.close()
default:
return experimentalsys.EINVAL
}
return experimentalsys.UnwrapOSError(err)
}