mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-07 04:23:41 +00:00
WASI & darwin: support basic file io based on libc
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
committed by
Ron Evans
parent
6d3c11627c
commit
1406453350
@@ -0,0 +1,5 @@
|
||||
// +build !wasi,!darwin
|
||||
|
||||
package syscall
|
||||
|
||||
func (e Errno) Is(target error) bool { return false }
|
||||
@@ -13,12 +13,15 @@ type sliceHeader struct {
|
||||
}
|
||||
|
||||
func Close(fd int) (err error) {
|
||||
return ENOSYS // TODO
|
||||
if libc_close(fd) < 0 {
|
||||
err = getErrno()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Write(fd int, p []byte) (n int, err error) {
|
||||
buf, count := splitSlice(p)
|
||||
n = libc_write(int32(fd), buf, uint(count))
|
||||
n = libc_write(fd, buf, uint(count))
|
||||
if n < 0 {
|
||||
err = getErrno()
|
||||
}
|
||||
@@ -26,15 +29,25 @@ func Write(fd int, p []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func Read(fd int, p []byte) (n int, err error) {
|
||||
return 0, ENOSYS // TODO
|
||||
buf, count := splitSlice(p)
|
||||
n = libc_read(fd, buf, uint(count))
|
||||
if n < 0 {
|
||||
err = getErrno()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Seek(fd int, offset int64, whence int) (off int64, err error) {
|
||||
return 0, ENOSYS // TODO
|
||||
}
|
||||
|
||||
func Open(path string, mode int, perm uint32) (fd int, err error) {
|
||||
return 0, ENOSYS // TODO
|
||||
func Open(path string, flag int, mode uint32) (fd int, err error) {
|
||||
data := append([]byte(path), 0)
|
||||
fd = libc_open(&data[0], flag, mode)
|
||||
if fd < 0 {
|
||||
err = getErrno()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Mkdir(path string, mode uint32) (err error) {
|
||||
@@ -78,8 +91,20 @@ func splitSlice(p []byte) (buf *byte, len uintptr) {
|
||||
|
||||
// ssize_t write(int fd, const void *buf, size_t count)
|
||||
//export write
|
||||
func libc_write(fd int32, buf *byte, count uint) int
|
||||
func libc_write(fd int, buf *byte, count uint) int
|
||||
|
||||
// char *getenv(const char *name);
|
||||
//export getenv
|
||||
func libc_getenv(name *byte) *byte
|
||||
|
||||
// ssize_t read(int fd, void *buf, size_t count);
|
||||
//export read
|
||||
func libc_read(fd int, buf *byte, count uint) int
|
||||
|
||||
// int open(const char *pathname, int flags, mode_t mode);
|
||||
//export open
|
||||
func libc_open(pathname *byte, flags int, mode uint32) int
|
||||
|
||||
// int close(int fd)
|
||||
//export close
|
||||
func libc_close(fd int) int
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build darwin
|
||||
|
||||
package syscall
|
||||
|
||||
// This file defines errno and constants to match the darwin libsystem ABI.
|
||||
@@ -22,10 +24,25 @@ func getErrno() Errno {
|
||||
return Errno(uintptr(*errptr))
|
||||
}
|
||||
|
||||
func (e Errno) Is(target error) bool {
|
||||
switch target.Error() {
|
||||
case "permission denied":
|
||||
return e == EACCES || e == EPERM
|
||||
case "file already exists":
|
||||
return e == EEXIST
|
||||
case "file does not exist":
|
||||
return e == ENOENT
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
EPERM Errno = 0x1
|
||||
ENOENT Errno = 0x2
|
||||
EACCES Errno = 0xd
|
||||
EEXIST Errno = 0x11
|
||||
EINTR Errno = 0x4
|
||||
ENOTDIR Errno = 0x14
|
||||
EMFILE Errno = 0x18
|
||||
EAGAIN Errno = 0x23
|
||||
ETIMEDOUT Errno = 0x3c
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
package syscall
|
||||
|
||||
import "errors"
|
||||
|
||||
// A Signal is a number describing a process signal.
|
||||
// It implements the os.Signal interface.
|
||||
type Signal int
|
||||
@@ -32,7 +30,6 @@ const (
|
||||
O_RDWR = 2
|
||||
|
||||
O_CREAT = 0100
|
||||
O_CREATE = O_CREAT
|
||||
O_TRUNC = 01000
|
||||
O_APPEND = 02000
|
||||
O_EXCL = 0200
|
||||
@@ -41,8 +38,9 @@ const (
|
||||
O_CLOEXEC = 0
|
||||
)
|
||||
|
||||
var dummyError = errors.New("unknown syscall error")
|
||||
//go:extern errno
|
||||
var libcErrno uintptr
|
||||
|
||||
func getErrno() error {
|
||||
return dummyError
|
||||
return Errno(libcErrno)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ const (
|
||||
O_RDWR = O_RDONLY | O_WRONLY
|
||||
|
||||
O_CREAT = __WASI_OFLAGS_CREAT << 12
|
||||
O_CREATE = O_CREAT
|
||||
O_TRUNC = __WASI_OFLAGS_TRUNC << 12
|
||||
O_APPEND = __WASI_FDFLAGS_APPEND
|
||||
O_EXCL = __WASI_OFLAGS_EXCL << 12
|
||||
@@ -48,3 +47,95 @@ var libcErrno uintptr
|
||||
func getErrno() error {
|
||||
return Errno(libcErrno)
|
||||
}
|
||||
|
||||
func (e Errno) Is(target error) bool {
|
||||
switch target.Error() {
|
||||
case "permission denied":
|
||||
return e == EACCES || e == EPERM || e == ENOTCAPABLE // ENOTCAPABLE is unique in WASI
|
||||
case "file already exists":
|
||||
return e == EEXIST || e == ENOTEMPTY
|
||||
case "file does not exist":
|
||||
return e == ENOENT
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__errno.h
|
||||
const (
|
||||
E2BIG Errno = 1 /* Argument list too long */
|
||||
EACCES Errno = 2 /* Permission denied */
|
||||
EADDRINUSE Errno = 3 /* Address already in use */
|
||||
EADDRNOTAVAIL Errno = 4 /* Address not available */
|
||||
EAFNOSUPPORT Errno = 5 /* Address family not supported by protocol family */
|
||||
EAGAIN Errno = 6 /* Try again */
|
||||
EWOULDBLOCK Errno = EAGAIN /* Operation would block */
|
||||
EALREADY Errno = 7 /* Socket already connected */
|
||||
EBADF Errno = 8 /* Bad file number */
|
||||
EBADMSG Errno = 9 /* Trying to read unreadable message */
|
||||
EBUSY Errno = 10 /* Device or resource busy */
|
||||
ECANCELED Errno = 11 /* Operation canceled. */
|
||||
ECHILD Errno = 12 /* No child processes */
|
||||
ECONNABORTED Errno = 13 /* Connection aborted */
|
||||
ECONNREFUSED Errno = 14 /* Connection refused */
|
||||
ECONNRESET Errno = 15 /* Connection reset by peer */
|
||||
EDEADLK Errno = 16 /* Deadlock condition */
|
||||
EDESTADDRREQ Errno = 17 /* Destination address required */
|
||||
EDOM Errno = 18 /* Math arg out of domain of func */
|
||||
EDQUOT Errno = 19 /* Quota exceeded */
|
||||
EEXIST Errno = 20 /* File exists */
|
||||
EFAULT Errno = 21 /* Bad address */
|
||||
EFBIG Errno = 22 /* File too large */
|
||||
EHOSTUNREACH Errno = 23 /* Host is unreachable */
|
||||
EIDRM Errno = 24 /* Identifier removed */
|
||||
EILSEQ Errno = 25
|
||||
EINPROGRESS Errno = 26 /* Connection already in progress */
|
||||
EINTR Errno = 27 /* Interrupted system call */
|
||||
EINVAL Errno = 28 /* Invalid argument */
|
||||
EIO Errno = 29 /* I/O error */
|
||||
EISCONN Errno = 30 /* Socket is already connected */
|
||||
EISDIR Errno = 31 /* Is a directory */
|
||||
ELOOP Errno = 32 /* Too many symbolic links */
|
||||
EMFILE Errno = 33 /* Too many open files */
|
||||
EMLINK Errno = 34 /* Too many links */
|
||||
EMSGSIZE Errno = 35 /* Message too long */
|
||||
EMULTIHOP Errno = 36 /* Multihop attempted */
|
||||
ENAMETOOLONG Errno = 37 /* File name too long */
|
||||
ENETDOWN Errno = 38 /* Network interface is not configured */
|
||||
ENETRESET Errno = 39
|
||||
ENETUNREACH Errno = 40 /* Network is unreachable */
|
||||
ENFILE Errno = 41 /* File table overflow */
|
||||
ENOBUFS Errno = 42 /* No buffer space available */
|
||||
ENODEV Errno = 43 /* No such device */
|
||||
ENOENT Errno = 44 /* No such file or directory */
|
||||
ENOEXEC Errno = 45 /* Exec format error */
|
||||
ENOLCK Errno = 46 /* No record locks available */
|
||||
ENOLINK Errno = 47 /* The link has been severed */
|
||||
ENOMEM Errno = 48 /* Out of memory */
|
||||
ENOMSG Errno = 49 /* No message of desired type */
|
||||
ENOPROTOOPT Errno = 50 /* Protocol not available */
|
||||
ENOSPC Errno = 51 /* No space left on device */
|
||||
ENOSYS Errno = 52 /* Function not implemented */
|
||||
ENOTCONN Errno = 53 /* Socket is not connected */
|
||||
ENOTDIR Errno = 54 /* Not a directory */
|
||||
ENOTEMPTY Errno = 55 /* Directory not empty */
|
||||
ENOTSOCK Errno = 57 /* Socket operation on non-socket */
|
||||
ESOCKTNOSUPPORT Errno = 58 /* Socket type not supported */
|
||||
EOPNOTSUPP Errno = 58 /* Operation not supported on transport endpoint */
|
||||
ENOTSUP Errno = EOPNOTSUPP /* Not supported */
|
||||
ENOTTY Errno = 59 /* Not a typewriter */
|
||||
ENXIO Errno = 60 /* No such device or address */
|
||||
EOVERFLOW Errno = 61 /* Value too large for defined data type */
|
||||
EPERM Errno = 63 /* Operation not permitted */
|
||||
EPIPE Errno = 64 /* Broken pipe */
|
||||
EPROTO Errno = 65 /* Protocol error */
|
||||
EPROTONOSUPPORT Errno = 66 /* Unknown protocol */
|
||||
EPROTOTYPE Errno = 67 /* Protocol wrong type for socket */
|
||||
ERANGE Errno = 68 /* Math result not representable */
|
||||
EROFS Errno = 69 /* Read-only file system */
|
||||
ESPIPE Errno = 70 /* Illegal seek */
|
||||
ESRCH Errno = 71 /* No such process */
|
||||
ESTALE Errno = 72
|
||||
ETIMEDOUT Errno = 73 /* Connection timed out */
|
||||
EXDEV Errno = 75 /* Cross-device link */
|
||||
ENOTCAPABLE Errno = 76 /* Extension: Capabilities insufficient. */
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build baremetal nintendoswitch wasi
|
||||
// +build baremetal nintendoswitch
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
Reference in New Issue
Block a user