Browse Source

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.
pull/2321/head
Ayke van Laethem 4 years ago
committed by Ron Evans
parent
commit
718746dd21
  1. 12
      Makefile
  2. 4
      src/os/env.go
  3. 33
      src/os/exec.go
  4. 31
      src/os/file.go
  5. 2
      src/os/file_anyos.go
  6. 4
      src/os/file_other.go
  7. 19
      src/os/file_unix.go
  8. 17
      src/os/file_windows.go
  9. 32
      src/syscall/syscall_libc.go
  10. 26
      src/syscall/syscall_libc_darwin.go
  11. 7
      src/syscall/syscall_nonhosted.go
  12. 11
      testdata/env.go

12
Makefile

@ -200,31 +200,41 @@ test: wasi-libc
TEST_PACKAGES = \
compress/bzip2 \
compress/flate \
compress/zlib \
container/heap \
container/list \
container/ring \
crypto/des \
crypto/dsa \
crypto/elliptic/internal/fiat \
crypto/internal/subtle \
crypto/md5 \
crypto/rc4 \
crypto/sha1 \
crypto/sha256 \
crypto/sha512 \
debug/macho \
encoding \
encoding/ascii85 \
encoding/base32 \
encoding/csv \
encoding/hex \
go/scanner \
hash \
hash/adler32 \
hash/fnv \
hash/crc64 \
hash/fnv \
html \
index/suffixarray \
internal/itoa \
internal/profile \
math \
math/cmplx \
net/http/internal/ascii \
net/mail \
os \
path \
reflect \
testing \
testing/iotest \

4
src/os/env.go

@ -12,3 +12,7 @@ func Getenv(key string) string {
func LookupEnv(key string) (string, bool) {
return syscall.Getenv(key)
}
func Environ() []string {
return syscall.Environ()
}

33
src/os/exec.go

@ -16,3 +16,36 @@ func Getpid() int {
func Getppid() int {
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
}

31
src/os/file.go

@ -52,6 +52,16 @@ func Remove(path string) error {
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.
type File struct {
handle FileHandle
@ -187,6 +197,27 @@ func (e *PathError) Error() string {
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 (
O_RDONLY int = syscall.O_RDONLY
O_WRONLY int = syscall.O_WRONLY

2
src/os/file_anyos.go

@ -21,6 +21,8 @@ var (
Stderr = &File{unixFileHandle(syscall.Stderr), "/dev/stderr"}
)
const DevNull = "/dev/null"
// isOS indicates whether we're running on a real operating system with
// filesystem support.
const isOS = true

4
src/os/file_other.go

@ -48,3 +48,7 @@ func (f stdioFileHandle) Close() error {
//go:linkname putchar runtime.putchar
func putchar(c byte)
func Pipe() (r *File, w *File, err error) {
return nil, nil, ErrNotImplemented
}

19
src/os/file_unix.go

@ -2,4 +2,23 @@
package os
import "syscall"
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
}

17
src/os/file_windows.go

@ -5,3 +5,20 @@ package os
import "syscall"
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
}

32
src/syscall/syscall_libc.go

@ -81,6 +81,12 @@ func Kill(pid int, sig Signal) (err error) {
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) {
data := cstring(key)
raw := libc_getenv(&data[0])
@ -115,6 +121,26 @@ func Mprotect(b []byte, prot int) (err error) {
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.
func cstring(s string) []byte {
data := make([]byte, len(s)+1)
@ -128,6 +154,9 @@ func splitSlice(p []byte) (buf *byte, len uintptr) {
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)
//export write
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);
//export unlink
func libc_unlink(pathname *byte) int32
//go:extern environ
var libc_environ *unsafe.Pointer

26
src/syscall/syscall_libc_darwin.go

@ -36,18 +36,20 @@ func (e Errno) Is(target error) bool {
return false
}
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/errno.h.auto.html
const (
EPERM Errno = 0x1
ENOENT Errno = 0x2
EACCES Errno = 0xd
EEXIST Errno = 0x11
EINTR Errno = 0x4
ENOTDIR Errno = 0x14
EINVAL Errno = 0x16
EMFILE Errno = 0x18
EAGAIN Errno = 0x23
ETIMEDOUT Errno = 0x3c
ENOSYS Errno = 0x4e
EPERM Errno = 1
ENOENT Errno = 2
EACCES Errno = 13
EEXIST Errno = 17
EINTR Errno = 4
ENOTDIR Errno = 20
EINVAL Errno = 22
EMFILE Errno = 24
EPIPE Errno = 32
EAGAIN Errno = 35
ETIMEDOUT Errno = 60
ENOSYS Errno = 78
EWOULDBLOCK Errno = EAGAIN
)
@ -77,6 +79,8 @@ const (
O_CREAT = 0x200
O_TRUNC = 0x400
O_EXCL = 0x800
O_CLOEXEC = 0x01000000
)
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html

7
src/syscall/syscall_nonhosted.go

@ -67,6 +67,13 @@ func Getenv(key string) (value string, found bool) {
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) {
return 0, ENOSYS
}

11
testdata/env.go

@ -13,6 +13,17 @@ func main() {
}
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.
// Argument 0 is skipped because it is the program name, which varies by
// test run.

Loading…
Cancel
Save