make runtime compatible with wasm

This commit is contained in:
Li Jie
2025-04-08 16:50:47 +08:00
parent 7c81d9293b
commit be4737461a
183 changed files with 14122 additions and 647 deletions

View File

@@ -8,8 +8,8 @@ import (
c "github.com/goplus/llgo/runtime/internal/clite"
"github.com/goplus/llgo/runtime/internal/clite/os"
"github.com/goplus/llgo/runtime/internal/clite/syscall"
"github.com/goplus/llgo/runtime/internal/lib/internal/bytealg"
"github.com/goplus/llgo/runtime/internal/lib/syscall"
)
type readdirMode int
@@ -39,7 +39,7 @@ func (f *File) Readdirnames(n int) (names []string, err error) {
}
func open(path string, flag int, perm uint32) (int, error) {
fd, err := syscall.Open(path, flag, perm)
fd, err := origSyscall.Open(path, flag, perm)
return fd, err
}
@@ -100,10 +100,29 @@ func closedir(dir uintptr) error {
}
//go:linkname c_readdir C.readdir
func c_readdir(dir uintptr) ([]syscall.Dirent, error)
func c_readdir(dir uintptr) *syscall.Dirent
func readdir(dir uintptr) ([]syscall.Dirent, error) {
return c_readdir(dir)
var entries []syscall.Dirent
for {
dirent := c_readdir(dir)
if dirent == nil {
break
}
entries = append(entries, *dirent)
}
return entries, nil
}
func direntNamePtr(name any) *byte {
switch name := name.(type) {
case *byte:
return name
case []byte:
return &name[0]
default:
panic("invalid type")
}
}
func (f *File) ReadDir(n int) (dirents []DirEntry, err error) {
@@ -133,26 +152,26 @@ func (f *File) ReadDir(n int) (dirents []DirEntry, err error) {
for _, entry := range entries {
// Convert syscall.Dirent to fs.DirEntry
name := bytesToString((*[1024]byte)(unsafe.Pointer(&entry.Name[0]))[:])
name := bytesToString((*[1024]byte)(unsafe.Pointer(direntNamePtr(entry.Name)))[:])
if name == "." || name == ".." {
continue
}
typ := fs.FileMode(0)
switch entry.Type {
case origSyscall.DT_REG:
case syscall.DT_REG:
typ = 0
case origSyscall.DT_DIR:
case syscall.DT_DIR:
typ = fs.ModeDir
case origSyscall.DT_LNK:
case syscall.DT_LNK:
typ = fs.ModeSymlink
case origSyscall.DT_SOCK:
case syscall.DT_SOCK:
typ = fs.ModeSocket
case origSyscall.DT_FIFO:
case syscall.DT_FIFO:
typ = fs.ModeNamedPipe
case origSyscall.DT_CHR:
case syscall.DT_CHR:
typ = fs.ModeCharDevice
case origSyscall.DT_BLK:
case syscall.DT_BLK:
typ = fs.ModeDevice
}

View File

@@ -208,15 +208,6 @@ func (f *File) WriteString(s string) (n int, err error) {
panic("todo: os.(*File).WriteString")
}
// setStickyBit adds ModeSticky to the permission bits of path, non atomic.
func setStickyBit(name string) error {
fi, err := Stat(name)
if err != nil {
return err
}
return Chmod(name, fi.Mode()|ModeSticky)
}
// Open opens the named file for reading. If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
@@ -476,7 +467,6 @@ func ReadFile(name string) ([]byte, error) {
if err != nil {
return nil, err
}
defer f.Close()
var size int
if info, err := f.Stat(); err == nil {
@@ -507,6 +497,7 @@ func ReadFile(name string) ([]byte, error) {
if err == io.EOF {
err = nil
}
f.Close()
return data, err
}
}

View File

@@ -80,44 +80,6 @@ func Chdir(dir string) error {
}
*/
func Chmod(name string, mode FileMode) error {
ret := os.Chmod(c.AllocaCStr(name), os.ModeT(syscallMode(mode)))
if ret == 0 {
return nil
}
return toPathErr("chmod", name, ret)
}
/* TODO(xsw):
// Chmod changes the mode of the named file to mode.
// If the file is a symbolic link, it changes the mode of the link's target.
// If there is an error, it will be of type *PathError.
//
// A different subset of the mode bits are used, depending on the
// operating system.
//
// On Unix, the mode's permission bits, ModeSetuid, ModeSetgid, and
// ModeSticky are used.
//
// On Windows, only the 0200 bit (owner writable) of mode is used; it
// controls whether the file's read-only attribute is set or cleared.
// The other bits are currently unused. For compatibility with Go 1.12
// and earlier, use a non-zero mode. Use mode 0400 for a read-only
// file and 0600 for a readable+writable file.
//
// On Plan 9, the mode's permission bits, ModeAppend, ModeExclusive,
// and ModeTemporary are used.
func Chmod(name string, mode FileMode) error { return chmod(name, mode) }
*/
func Chown(name string, uid, gid int) error {
ret := os.Chown(c.AllocaCStr(name), os.UidT(uid), os.GidT(gid))
if ret == 0 {
return nil
}
return toPathErr("chown", name, ret)
}
/* TODO(xsw):
// Chown changes the numeric uid and gid of the named file.
// If the file is a symbolic link, it changes the uid and gid of the link's target.
@@ -152,34 +114,6 @@ func Clearenv()
// func Expand(s string, mapping func(string) string) string
// func ExpandEnv(s string) string
func Getegid() int {
return int(os.Getegid())
}
func Geteuid() int {
return int(os.Geteuid())
}
func Getgid() int {
return int(os.Getgid())
}
// TODO(xsw):
// func Getgroups() ([]int, error)
// func Getpagesize() int
func Getpid() int {
return int(os.Getpid())
}
func Getppid() int {
return int(os.Getppid())
}
func Getuid() int {
return int(os.Getuid())
}
func Getwd() (dir string, err error) {
wd := os.Getcwd(c.Alloca(os.PATH_MAX), os.PATH_MAX)
if wd != nil {
@@ -195,32 +129,6 @@ func Getwd() (dir string, err error) {
// func IsPermission(err error) bool
// func IsTimeout(err error) bool
func Lchown(name string, uid, gid int) error {
ret := os.Lchown(c.AllocaCStr(name), os.UidT(uid), os.GidT(gid))
if ret == 0 {
return nil
}
return toPathErr("lchown", name, ret)
}
/* TODO(xsw):
// Lchown changes the numeric uid and gid of the named file.
// If the file is a symbolic link, it changes the uid and gid of the link itself.
// If there is an error, it will be of type *PathError.
//
// On Windows, it always returns the syscall.EWINDOWS error, wrapped
// in *PathError.
func Lchown(name string, uid, gid int) error {
e := ignoringEINTR(func() error {
return syscall.Lchown(name, uid, gid)
})
if e != nil {
return &PathError{Op: "lchown", Path: name, Err: e}
}
return nil
}
*/
func Link(oldname, newname string) error {
ret := os.Link(c.AllocaCStr(oldname), c.AllocaCStr(newname))
if ret == 0 {

View File

@@ -0,0 +1,109 @@
//go:build !wasm
package os
import (
c "github.com/goplus/llgo/runtime/internal/clite"
"github.com/goplus/llgo/runtime/internal/clite/os"
)
// setStickyBit adds ModeSticky to the permission bits of path, non atomic.
func setStickyBit(name string) error {
fi, err := Stat(name)
if err != nil {
return err
}
return Chmod(name, fi.Mode()|ModeSticky)
}
func Chmod(name string, mode FileMode) error {
ret := os.Chmod(c.AllocaCStr(name), os.ModeT(syscallMode(mode)))
if ret == 0 {
return nil
}
return toPathErr("chmod", name, ret)
}
/* TODO(xsw):
// Chmod changes the mode of the named file to mode.
// If the file is a symbolic link, it changes the mode of the link's target.
// If there is an error, it will be of type *PathError.
//
// A different subset of the mode bits are used, depending on the
// operating system.
//
// On Unix, the mode's permission bits, ModeSetuid, ModeSetgid, and
// ModeSticky are used.
//
// On Windows, only the 0200 bit (owner writable) of mode is used; it
// controls whether the file's read-only attribute is set or cleared.
// The other bits are currently unused. For compatibility with Go 1.12
// and earlier, use a non-zero mode. Use mode 0400 for a read-only
// file and 0600 for a readable+writable file.
//
// On Plan 9, the mode's permission bits, ModeAppend, ModeExclusive,
// and ModeTemporary are used.
func Chmod(name string, mode FileMode) error { return chmod(name, mode) }
*/
func Chown(name string, uid, gid int) error {
ret := os.Chown(c.AllocaCStr(name), os.UidT(uid), os.GidT(gid))
if ret == 0 {
return nil
}
return toPathErr("chown", name, ret)
}
func Getegid() int {
return int(os.Getegid())
}
func Geteuid() int {
return int(os.Geteuid())
}
func Getgid() int {
return int(os.Getgid())
}
// TODO(xsw):
// func Getgroups() ([]int, error)
// func Getpagesize() int
func Getpid() int {
return int(os.Getpid())
}
func Getppid() int {
return int(os.Getppid())
}
func Getuid() int {
return int(os.Getuid())
}
func Lchown(name string, uid, gid int) error {
ret := os.Lchown(c.AllocaCStr(name), os.UidT(uid), os.GidT(gid))
if ret == 0 {
return nil
}
return toPathErr("lchown", name, ret)
}
/* TODO(xsw):
// Lchown changes the numeric uid and gid of the named file.
// If the file is a symbolic link, it changes the uid and gid of the link itself.
// If there is an error, it will be of type *PathError.
//
// On Windows, it always returns the syscall.EWINDOWS error, wrapped
// in *PathError.
func Lchown(name string, uid, gid int) error {
e := ignoringEINTR(func() error {
return syscall.Lchown(name, uid, gid)
})
if e != nil {
return &PathError{Op: "lchown", Path: name, Err: e}
}
return nil
}
*/

View File

@@ -0,0 +1,10 @@
package os
// setStickyBit adds ModeSticky to the permission bits of path, non atomic.
func setStickyBit(name string) error {
return nil
}
func Chmod(name string, mode FileMode) error {
return nil
}

View File

@@ -57,3 +57,14 @@ func MkdirAll(path string, perm FileMode) error {
func RemoveAll(path string) error {
return removeAll(path)
}
// endsWithDot reports whether the final component of path is ".".
func endsWithDot(path string) bool {
if path == "." {
return true
}
if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
return true
}
return false
}

View File

@@ -209,14 +209,3 @@ func openDirAt(dirfd int, name string) (*File, error) {
// We use kindNoPoll because we know that this is a directory.
return newFile(r, name, kindNoPoll), nil
}
// endsWithDot reports whether the final component of path is ".".
func endsWithDot(path string) bool {
if path == "." {
return true
}
if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
return true
}
return false
}

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build unix || (js && wasm) || wasip1
//go:build unix || wasm
package os
@@ -23,7 +23,6 @@ func (f *File) Stat() (FileInfo, error) {
if err != 0 {
return nil, &PathError{Op: "stat", Path: f.name, Err: syscall.Errno(err)}
}
fillFileStatFromSys(&fs, f.name)
return &fs, nil
}
@@ -36,7 +35,6 @@ func statNolog(name string) (FileInfo, error) {
if err != nil {
return nil, &PathError{Op: "stat", Path: name, Err: err}
}
fillFileStatFromSys(&fs, name)
return &fs, nil
}
@@ -49,6 +47,5 @@ func lstatNolog(name string) (FileInfo, error) {
if err != nil {
return nil, &PathError{Op: "lstat", Path: name, Err: err}
}
fillFileStatFromSys(&fs, name)
return &fs, nil
}

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build js && wasm
//go:build js && !wasm
package os

View File

@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build wasip1
package os
// supportsCloseOnExec reports whether the platform supports the