89 lines
2.7 KiB
Go
89 lines
2.7 KiB
Go
package sysfs
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/tetratelabs/wazero/experimental/sys"
|
|
)
|
|
|
|
const (
|
|
nonBlockingFileReadSupported = true
|
|
nonBlockingFileWriteSupported = false
|
|
)
|
|
|
|
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
|
|
// procPeekNamedPipe is the syscall.LazyProc in kernel32 for PeekNamedPipe
|
|
var procPeekNamedPipe = kernel32.NewProc("PeekNamedPipe")
|
|
|
|
// readFd returns ENOSYS on unsupported platforms.
|
|
//
|
|
// PeekNamedPipe: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe
|
|
// "GetFileType can assist in determining what device type the handle refers to. A console handle presents as FILE_TYPE_CHAR."
|
|
// https://learn.microsoft.com/en-us/windows/console/console-handles
|
|
func readFd(fd uintptr, buf []byte) (int, sys.Errno) {
|
|
handle := syscall.Handle(fd)
|
|
fileType, err := syscall.GetFileType(handle)
|
|
if err != nil {
|
|
return 0, sys.UnwrapOSError(err)
|
|
}
|
|
if fileType&syscall.FILE_TYPE_CHAR == 0 {
|
|
return -1, sys.ENOSYS
|
|
}
|
|
n, errno := peekNamedPipe(handle)
|
|
if errno == syscall.ERROR_BROKEN_PIPE {
|
|
return 0, 0
|
|
}
|
|
if n == 0 {
|
|
return -1, sys.EAGAIN
|
|
}
|
|
un, err := syscall.Read(handle, buf[0:n])
|
|
return un, sys.UnwrapOSError(err)
|
|
}
|
|
|
|
func writeFd(fd uintptr, buf []byte) (int, sys.Errno) {
|
|
return -1, sys.ENOSYS
|
|
}
|
|
|
|
func readSocket(h syscall.Handle, buf []byte) (int, sys.Errno) {
|
|
var overlapped syscall.Overlapped
|
|
var done uint32
|
|
errno := syscall.ReadFile(h, buf, &done, &overlapped)
|
|
if errno == syscall.ERROR_IO_PENDING {
|
|
errno = sys.EAGAIN
|
|
}
|
|
return int(done), sys.UnwrapOSError(errno)
|
|
}
|
|
|
|
func writeSocket(fd uintptr, buf []byte) (int, sys.Errno) {
|
|
var done uint32
|
|
var overlapped syscall.Overlapped
|
|
errno := syscall.WriteFile(syscall.Handle(fd), buf, &done, &overlapped)
|
|
if errno == syscall.ERROR_IO_PENDING {
|
|
errno = syscall.EAGAIN
|
|
}
|
|
return int(done), sys.UnwrapOSError(errno)
|
|
}
|
|
|
|
// peekNamedPipe partially exposes PeekNamedPipe from the Win32 API
|
|
// see https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe
|
|
func peekNamedPipe(handle syscall.Handle) (uint32, syscall.Errno) {
|
|
var totalBytesAvail uint32
|
|
totalBytesPtr := unsafe.Pointer(&totalBytesAvail)
|
|
_, _, errno := syscall.SyscallN(
|
|
procPeekNamedPipe.Addr(),
|
|
uintptr(handle), // [in] HANDLE hNamedPipe,
|
|
0, // [out, optional] LPVOID lpBuffer,
|
|
0, // [in] DWORD nBufferSize,
|
|
0, // [out, optional] LPDWORD lpBytesRead
|
|
uintptr(totalBytesPtr), // [out, optional] LPDWORD lpTotalBytesAvail,
|
|
0) // [out, optional] LPDWORD lpBytesLeftThisMessage
|
|
return totalBytesAvail, errno
|
|
}
|
|
|
|
func rmdir(path string) sys.Errno {
|
|
err := syscall.Rmdir(path)
|
|
return sys.UnwrapOSError(err)
|
|
}
|