diff --git a/internal/sysfs/dirfs.go b/internal/sysfs/dirfs.go index 05d5b647..36100ca4 100644 --- a/internal/sysfs/dirfs.go +++ b/internal/sysfs/dirfs.go @@ -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)) diff --git a/internal/sysfs/dirfs_link_supported.go b/internal/sysfs/dirfs_link_supported.go new file mode 100644 index 00000000..d9fbdaa5 --- /dev/null +++ b/internal/sysfs/dirfs_link_supported.go @@ -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) +} diff --git a/internal/sysfs/dirfs_link_unsupported.go b/internal/sysfs/dirfs_link_unsupported.go new file mode 100644 index 00000000..427f306d --- /dev/null +++ b/internal/sysfs/dirfs_link_unsupported.go @@ -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 +} diff --git a/internal/sysfs/sock.go b/internal/sysfs/sock.go index 8f8e6def..ab9bb1ff 100644 --- a/internal/sysfs/sock.go +++ b/internal/sysfs/sock.go @@ -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() diff --git a/internal/sysfs/sock_supported.go b/internal/sysfs/sock_supported.go index 747393b4..6c976fb8 100644 --- a/internal/sysfs/sock_supported.go +++ b/internal/sysfs/sock_supported.go @@ -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. // diff --git a/internal/sysfs/sock_unix.go b/internal/sysfs/sock_unix.go index 0f570f37..99ef018a 100644 --- a/internal/sysfs/sock_unix.go +++ b/internal/sysfs/sock_unix.go @@ -1,4 +1,4 @@ -//go:build linux || darwin +//go:build (linux || darwin) && !tinygo package sysfs diff --git a/internal/sysfs/sock_unsupported.go b/internal/sysfs/sock_unsupported.go index cee02742..8c27fed7 100644 --- a/internal/sysfs/sock_unsupported.go +++ b/internal/sysfs/sock_unsupported.go @@ -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) +}