os: stub out support for some more features
This is necessary for the following: - to make sure os/exec can be imported - to make sure internal/testenv can be imported The internal/testenv package (which imports os/exec) is used by a lot of tests. By adding support for it, more tests can be run. This commit adds a bunch of new packages that now pass all tests.
Этот коммит содержится в:
родитель
6cbaed75c8
коммит
718746dd21
12 изменённых файлов: 186 добавлений и 12 удалений
12
Makefile
12
Makefile
|
@ -200,31 +200,41 @@ test: wasi-libc
|
||||||
|
|
||||||
TEST_PACKAGES = \
|
TEST_PACKAGES = \
|
||||||
compress/bzip2 \
|
compress/bzip2 \
|
||||||
|
compress/flate \
|
||||||
|
compress/zlib \
|
||||||
container/heap \
|
container/heap \
|
||||||
container/list \
|
container/list \
|
||||||
container/ring \
|
container/ring \
|
||||||
crypto/des \
|
crypto/des \
|
||||||
crypto/dsa \
|
crypto/dsa \
|
||||||
|
crypto/elliptic/internal/fiat \
|
||||||
|
crypto/internal/subtle \
|
||||||
crypto/md5 \
|
crypto/md5 \
|
||||||
crypto/rc4 \
|
crypto/rc4 \
|
||||||
crypto/sha1 \
|
crypto/sha1 \
|
||||||
crypto/sha256 \
|
crypto/sha256 \
|
||||||
crypto/sha512 \
|
crypto/sha512 \
|
||||||
|
debug/macho \
|
||||||
encoding \
|
encoding \
|
||||||
encoding/ascii85 \
|
encoding/ascii85 \
|
||||||
encoding/base32 \
|
encoding/base32 \
|
||||||
|
encoding/csv \
|
||||||
encoding/hex \
|
encoding/hex \
|
||||||
|
go/scanner \
|
||||||
hash \
|
hash \
|
||||||
hash/adler32 \
|
hash/adler32 \
|
||||||
hash/fnv \
|
|
||||||
hash/crc64 \
|
hash/crc64 \
|
||||||
|
hash/fnv \
|
||||||
html \
|
html \
|
||||||
index/suffixarray \
|
index/suffixarray \
|
||||||
internal/itoa \
|
internal/itoa \
|
||||||
|
internal/profile \
|
||||||
math \
|
math \
|
||||||
math/cmplx \
|
math/cmplx \
|
||||||
|
net/http/internal/ascii \
|
||||||
net/mail \
|
net/mail \
|
||||||
os \
|
os \
|
||||||
|
path \
|
||||||
reflect \
|
reflect \
|
||||||
testing \
|
testing \
|
||||||
testing/iotest \
|
testing/iotest \
|
||||||
|
|
|
@ -12,3 +12,7 @@ func Getenv(key string) string {
|
||||||
func LookupEnv(key string) (string, bool) {
|
func LookupEnv(key string) (string, bool) {
|
||||||
return syscall.Getenv(key)
|
return syscall.Getenv(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
return syscall.Environ()
|
||||||
|
}
|
||||||
|
|
|
@ -16,3 +16,36 @@ func Getpid() int {
|
||||||
func Getppid() int {
|
func Getppid() int {
|
||||||
return syscall.Getppid()
|
return syscall.Getppid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProcAttr struct {
|
||||||
|
Dir string
|
||||||
|
Env []string
|
||||||
|
Files []*File
|
||||||
|
Sys *syscall.SysProcAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessState struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProcessState) String() string {
|
||||||
|
return "" // TODO
|
||||||
|
}
|
||||||
|
func (p *ProcessState) Success() bool {
|
||||||
|
return false // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
type Process struct {
|
||||||
|
Pid int
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
|
||||||
|
return nil, &PathError{"fork/exec", name, ErrNotImplemented}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Process) Wait() (*ProcessState, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Process) Kill() error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
|
@ -52,6 +52,16 @@ func Remove(path string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Symlink is a stub, it is not implemented.
|
||||||
|
func Symlink(oldname, newname string) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAll is a stub, it is not implemented.
|
||||||
|
func RemoveAll(path string) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// File represents an open file descriptor.
|
// File represents an open file descriptor.
|
||||||
type File struct {
|
type File struct {
|
||||||
handle FileHandle
|
handle FileHandle
|
||||||
|
@ -187,6 +197,27 @@ func (e *PathError) Error() string {
|
||||||
return e.Op + " " + e.Path + ": " + e.Err.Error()
|
return e.Op + " " + e.Path + ": " + e.Err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *PathError) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkError records an error during a link or symlink or rename system call and
|
||||||
|
// the paths that caused it.
|
||||||
|
type LinkError struct {
|
||||||
|
Op string
|
||||||
|
Old string
|
||||||
|
New string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *LinkError) Error() string {
|
||||||
|
return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *LinkError) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
O_RDONLY int = syscall.O_RDONLY
|
O_RDONLY int = syscall.O_RDONLY
|
||||||
O_WRONLY int = syscall.O_WRONLY
|
O_WRONLY int = syscall.O_WRONLY
|
||||||
|
|
|
@ -21,6 +21,8 @@ var (
|
||||||
Stderr = &File{unixFileHandle(syscall.Stderr), "/dev/stderr"}
|
Stderr = &File{unixFileHandle(syscall.Stderr), "/dev/stderr"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DevNull = "/dev/null"
|
||||||
|
|
||||||
// isOS indicates whether we're running on a real operating system with
|
// isOS indicates whether we're running on a real operating system with
|
||||||
// filesystem support.
|
// filesystem support.
|
||||||
const isOS = true
|
const isOS = true
|
||||||
|
|
|
@ -48,3 +48,7 @@ func (f stdioFileHandle) Close() error {
|
||||||
|
|
||||||
//go:linkname putchar runtime.putchar
|
//go:linkname putchar runtime.putchar
|
||||||
func putchar(c byte)
|
func putchar(c byte)
|
||||||
|
|
||||||
|
func Pipe() (r *File, w *File, err error) {
|
||||||
|
return nil, nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
|
@ -2,4 +2,23 @@
|
||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
type syscallFd = int
|
type syscallFd = int
|
||||||
|
|
||||||
|
func Pipe() (r *File, w *File, err error) {
|
||||||
|
var p [2]int
|
||||||
|
err = handleSyscallError(syscall.Pipe2(p[:], syscall.O_CLOEXEC))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r = &File{
|
||||||
|
handle: unixFileHandle(p[0]),
|
||||||
|
name: "|0",
|
||||||
|
}
|
||||||
|
w = &File{
|
||||||
|
handle: unixFileHandle(p[1]),
|
||||||
|
name: "|1",
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -5,3 +5,20 @@ package os
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
type syscallFd = syscall.Handle
|
type syscallFd = syscall.Handle
|
||||||
|
|
||||||
|
func Pipe() (r *File, w *File, err error) {
|
||||||
|
var p [2]syscall.Handle
|
||||||
|
e := handleSyscallError(syscall.Pipe(p[:]))
|
||||||
|
if e != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r = &File{
|
||||||
|
handle: unixFileHandle(p[0]),
|
||||||
|
name: "|0",
|
||||||
|
}
|
||||||
|
w = &File{
|
||||||
|
handle: unixFileHandle(p[1]),
|
||||||
|
name: "|1",
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -81,6 +81,12 @@ func Kill(pid int, sig Signal) (err error) {
|
||||||
return ENOSYS // TODO
|
return ENOSYS // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SysProcAttr struct{}
|
||||||
|
|
||||||
|
func Pipe2(p []int, flags int) (err error) {
|
||||||
|
return ENOSYS // TODO
|
||||||
|
}
|
||||||
|
|
||||||
func Getenv(key string) (value string, found bool) {
|
func Getenv(key string) (value string, found bool) {
|
||||||
data := cstring(key)
|
data := cstring(key)
|
||||||
raw := libc_getenv(&data[0])
|
raw := libc_getenv(&data[0])
|
||||||
|
@ -115,6 +121,26 @@ func Mprotect(b []byte, prot int) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
environ := libc_environ
|
||||||
|
var envs []string
|
||||||
|
for *environ != nil {
|
||||||
|
// Convert the C string to a Go string.
|
||||||
|
length := libc_strlen(*environ)
|
||||||
|
var envVar string
|
||||||
|
rawEnvVar := (*struct {
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
length uintptr
|
||||||
|
})(unsafe.Pointer(&envVar))
|
||||||
|
rawEnvVar.ptr = *environ
|
||||||
|
rawEnvVar.length = length
|
||||||
|
envs = append(envs, envVar)
|
||||||
|
// This is the Go equivalent of "environ++" in C.
|
||||||
|
environ = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(environ)) + unsafe.Sizeof(environ)))
|
||||||
|
}
|
||||||
|
return envs
|
||||||
|
}
|
||||||
|
|
||||||
// cstring converts a Go string to a C string.
|
// cstring converts a Go string to a C string.
|
||||||
func cstring(s string) []byte {
|
func cstring(s string) []byte {
|
||||||
data := make([]byte, len(s)+1)
|
data := make([]byte, len(s)+1)
|
||||||
|
@ -128,6 +154,9 @@ func splitSlice(p []byte) (buf *byte, len uintptr) {
|
||||||
return slice.buf, slice.len
|
return slice.buf, slice.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export strlen
|
||||||
|
func libc_strlen(ptr unsafe.Pointer) uintptr
|
||||||
|
|
||||||
// ssize_t write(int fd, const void *buf, size_t count)
|
// ssize_t write(int fd, const void *buf, size_t count)
|
||||||
//export write
|
//export write
|
||||||
func libc_write(fd int32, buf *byte, count uint) int
|
func libc_write(fd int32, buf *byte, count uint) int
|
||||||
|
@ -167,3 +196,6 @@ func libc_rmdir(pathname *byte) int32
|
||||||
// int unlink(const char *pathname);
|
// int unlink(const char *pathname);
|
||||||
//export unlink
|
//export unlink
|
||||||
func libc_unlink(pathname *byte) int32
|
func libc_unlink(pathname *byte) int32
|
||||||
|
|
||||||
|
//go:extern environ
|
||||||
|
var libc_environ *unsafe.Pointer
|
||||||
|
|
|
@ -36,18 +36,20 @@ func (e Errno) Is(target error) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/errno.h.auto.html
|
||||||
const (
|
const (
|
||||||
EPERM Errno = 0x1
|
EPERM Errno = 1
|
||||||
ENOENT Errno = 0x2
|
ENOENT Errno = 2
|
||||||
EACCES Errno = 0xd
|
EACCES Errno = 13
|
||||||
EEXIST Errno = 0x11
|
EEXIST Errno = 17
|
||||||
EINTR Errno = 0x4
|
EINTR Errno = 4
|
||||||
ENOTDIR Errno = 0x14
|
ENOTDIR Errno = 20
|
||||||
EINVAL Errno = 0x16
|
EINVAL Errno = 22
|
||||||
EMFILE Errno = 0x18
|
EMFILE Errno = 24
|
||||||
EAGAIN Errno = 0x23
|
EPIPE Errno = 32
|
||||||
ETIMEDOUT Errno = 0x3c
|
EAGAIN Errno = 35
|
||||||
ENOSYS Errno = 0x4e
|
ETIMEDOUT Errno = 60
|
||||||
|
ENOSYS Errno = 78
|
||||||
EWOULDBLOCK Errno = EAGAIN
|
EWOULDBLOCK Errno = EAGAIN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,6 +79,8 @@ const (
|
||||||
O_CREAT = 0x200
|
O_CREAT = 0x200
|
||||||
O_TRUNC = 0x400
|
O_TRUNC = 0x400
|
||||||
O_EXCL = 0x800
|
O_EXCL = 0x800
|
||||||
|
|
||||||
|
O_CLOEXEC = 0x01000000
|
||||||
)
|
)
|
||||||
|
|
||||||
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html
|
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html
|
||||||
|
|
|
@ -67,6 +67,13 @@ func Getenv(key string) (value string, found bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
env := runtime_envs()
|
||||||
|
envCopy := make([]string, len(env))
|
||||||
|
copy(envCopy, env)
|
||||||
|
return envCopy
|
||||||
|
}
|
||||||
|
|
||||||
func Open(path string, mode int, perm uint32) (fd int, err error) {
|
func Open(path string, mode int, perm uint32) (fd int, err error) {
|
||||||
return 0, ENOSYS
|
return 0, ENOSYS
|
||||||
}
|
}
|
||||||
|
|
11
testdata/env.go
предоставленный
11
testdata/env.go
предоставленный
|
@ -13,6 +13,17 @@ func main() {
|
||||||
}
|
}
|
||||||
println("ENV2:", v)
|
println("ENV2:", v)
|
||||||
|
|
||||||
|
found := false
|
||||||
|
expected := "ENV1=" + os.Getenv("ENV1")
|
||||||
|
for _, envVar := range os.Environ() {
|
||||||
|
if envVar == expected {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
println("could not find " + expected + " in os.Environ()")
|
||||||
|
}
|
||||||
|
|
||||||
// Check for command line arguments.
|
// Check for command line arguments.
|
||||||
// Argument 0 is skipped because it is the program name, which varies by
|
// Argument 0 is skipped because it is the program name, which varies by
|
||||||
// test run.
|
// test run.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче