diff --git a/misc/wasm/go_wasi_wasm_exec b/misc/wasm/go_wasi_wasm_exec new file mode 100755 index 0000000000000..eac1ffd71d9f5 --- /dev/null +++ b/misc/wasm/go_wasi_wasm_exec @@ -0,0 +1,14 @@ +#!/bin/bash +# Copyright 2018 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +exec wasmtime --dir=/ --env=PWD=$PWD $1 -- "${@:2}" diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index 9c3b7b81ce1f2..f46dc653aa91d 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -828,7 +828,7 @@ func regAddr(reg int16) obj.Addr { // Most of the Go functions has a single parameter (PC_B) in // Wasm ABI. This is a list of exceptions. var notUsePC_B = map[string]bool{ - "_rt0_wasm_js": true, + "_rt0_wasm_wasi": true, "wasm_export_run": true, "wasm_export_resume": true, "wasm_export_getsp": true, @@ -877,7 +877,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { // Function starts with declaration of locals: numbers and types. // Some functions use a special calling convention. switch s.Name { - case "_rt0_wasm_js", "wasm_export_run", "wasm_export_resume", "wasm_export_getsp", "wasm_pc_f_loop", + case "_rt0_wasm_wasi", "wasm_export_run", "wasm_export_resume", "wasm_export_getsp", "wasm_pc_f_loop", "runtime.wasmMove", "runtime.wasmZero", "runtime.wasmDiv", "runtime.wasmTruncS", "runtime.wasmTruncU", "memeqbody": varDecls = []*varDecl{} useAssemblyRegMap() diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 6eba39bcf78a6..2cb3896cd1255 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1583,7 +1583,7 @@ func dwarfEnabled(ctxt *Link) bool { if *FlagS && ctxt.HeadType != objabi.Hdarwin { return false } - if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs { + if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs || ctxt.HeadType == objabi.Hwasi { return false } diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go index eb48ac842a56e..3c8368430229a 100644 --- a/src/cmd/link/internal/ld/sym.go +++ b/src/cmd/link/internal/ld/sym.go @@ -67,7 +67,7 @@ func (ctxt *Link) computeTLSOffset() { default: log.Fatalf("unknown thread-local storage offset for %v", ctxt.HeadType) - case objabi.Hplan9, objabi.Hwindows, objabi.Hjs, objabi.Haix: + case objabi.Hplan9, objabi.Hwindows, objabi.Hjs, objabi.Hwasi, objabi.Haix: break case objabi.Hlinux, diff --git a/src/cmd/link/internal/wasm/asm.go b/src/cmd/link/internal/wasm/asm.go index d0e9f6f07b004..371763019a94c 100644 --- a/src/cmd/link/internal/wasm/asm.go +++ b/src/cmd/link/internal/wasm/asm.go @@ -55,7 +55,8 @@ type wasmFuncType struct { } var wasmFuncTypes = map[string]*wasmFuncType{ - "_rt0_wasm_js": {Params: []byte{}}, // + "_rt0_wasm_wasi": {Params: []byte{}}, // + "wasm_export__start": {}, // "wasm_export_run": {Params: []byte{I32, I32}}, // argc, argv "wasm_export_resume": {Params: []byte{}}, // "wasm_export_getsp": {Results: []byte{I32}}, // sp @@ -348,18 +349,16 @@ func writeGlobalSec(ctxt *ld.Link) { func writeExportSec(ctxt *ld.Link, lenHostImports int) { sizeOffset := writeSecHeader(ctxt, sectionExport) - writeUleb128(ctxt.Out, 4) // number of exports + writeUleb128(ctxt.Out, 2) // number of exports - for _, name := range []string{"run", "resume", "getsp"} { - idx := uint32(lenHostImports) + uint32(ctxt.Syms.ROLookup("wasm_export_"+name, 0).Value>>16) - funcValueOffset - writeName(ctxt.Out, name) // inst.exports.run/resume/getsp in wasm_exec.js - ctxt.Out.WriteByte(0x00) // func export - writeUleb128(ctxt.Out, uint64(idx)) // funcidx - } + idx := uint32(lenHostImports) + uint32(ctxt.Syms.ROLookup("_rt0_wasm_wasi", 0).Value>>16) - funcValueOffset + writeName(ctxt.Out, "_start") // inst.exports.run/resume/getsp in wasm_exec.js + ctxt.Out.WriteByte(0x00) // func export + writeUleb128(ctxt.Out, uint64(idx)) // funcidx - writeName(ctxt.Out, "mem") // inst.exports.mem in wasm_exec.js - ctxt.Out.WriteByte(0x02) // mem export - writeUleb128(ctxt.Out, 0) // memidx + writeName(ctxt.Out, "memory") // inst.exports.mem in wasm_exec.js + ctxt.Out.WriteByte(0x02) // mem export + writeUleb128(ctxt.Out, 0) // memidx writeSecSize(ctxt, sizeOffset) } diff --git a/src/crypto/rand/rand_wasi.go b/src/crypto/rand/rand_wasi.go new file mode 100644 index 0000000000000..3db936101feaf --- /dev/null +++ b/src/crypto/rand/rand_wasi.go @@ -0,0 +1,21 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import "syscall" + +func init() { + Reader = &reader{} +} + +type reader struct{} + +func (r *reader) Read(b []byte) (int, error) { + err := syscall.RandomGet(b) + if err != nil { + return 0, err + } + return len(b), nil +} diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go index 1be4058bab723..e1ca36d184ec8 100644 --- a/src/crypto/x509/root_unix.go +++ b/src/crypto/x509/root_unix.go @@ -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 aix dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package x509 diff --git a/src/crypto/x509/root_wasi.go b/src/crypto/x509/root_wasi.go new file mode 100644 index 0000000000000..54aeed4091469 --- /dev/null +++ b/src/crypto/x509/root_wasi.go @@ -0,0 +1,8 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{} diff --git a/src/internal/poll/fcntl_js.go b/src/internal/poll/fcntl_nosys.go similarity index 93% rename from src/internal/poll/fcntl_js.go rename to src/internal/poll/fcntl_nosys.go index 120fc1195fe6e..09f68623fdc6a 100644 --- a/src/internal/poll/fcntl_js.go +++ b/src/internal/poll/fcntl_nosys.go @@ -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 js,wasm +// +build js,wasm wasi package poll diff --git a/src/internal/poll/fd_fsync_posix.go b/src/internal/poll/fd_fsync_posix.go index 69358297f4c0d..91085fe18f535 100644 --- a/src/internal/poll/fd_fsync_posix.go +++ b/src/internal/poll/fd_fsync_posix.go @@ -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 aix dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package poll diff --git a/src/internal/poll/fd_poll_js.go b/src/internal/poll/fd_poll_fake.go similarity index 99% rename from src/internal/poll/fd_poll_js.go rename to src/internal/poll/fd_poll_fake.go index 2bfeb0a0b7af9..5cee6571ae03d 100644 --- a/src/internal/poll/fd_poll_js.go +++ b/src/internal/poll/fd_poll_fake.go @@ -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 js,wasm +// +build js,wasm wasi package poll diff --git a/src/internal/poll/fd_posix.go b/src/internal/poll/fd_posix.go index d0bacdd473746..cd0705b8e1315 100644 --- a/src/internal/poll/fd_posix.go +++ b/src/internal/poll/fd_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package poll diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 8752450a1fdd0..62d428010450c 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package poll diff --git a/src/internal/poll/fd_wasi.go b/src/internal/poll/fd_wasi.go new file mode 100644 index 0000000000000..b89021d894a3c --- /dev/null +++ b/src/internal/poll/fd_wasi.go @@ -0,0 +1,30 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package poll + +import "syscall" + +// ReadDir wraps syscall.ReadDir. +// We treat this like an ordinary system call rather than a call +// that tries to fill the buffer. +func (fd *FD) ReadDir(buf []byte, cookie syscall.Dircookie_t) (int, error) { + if err := fd.incref(); err != nil { + return 0, err + } + defer fd.decref() + for { + n, err := syscall.ReadDir(fd.Sysfd, buf, cookie) + if err != nil { + n = 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + // Do not call eofError; caller does not expect to see io.EOF. + return n, err + } +} diff --git a/src/internal/poll/hook_unix.go b/src/internal/poll/hook_unix.go index 11f90e9696875..4559ffc85ca1b 100644 --- a/src/internal/poll/hook_unix.go +++ b/src/internal/poll/hook_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package poll diff --git a/src/internal/poll/sys_cloexec.go b/src/internal/poll/sys_cloexec.go index 7b87f136dfe53..1a9ff52425f3c 100644 --- a/src/internal/poll/sys_cloexec.go +++ b/src/internal/poll/sys_cloexec.go @@ -5,7 +5,7 @@ // This file implements sysSocket and accept for platforms that do not // provide a fast path for setting SetNonblock and CloseOnExec. -// +build aix darwin js,wasm solaris +// +build aix darwin js,wasm solaris wasi package poll diff --git a/src/internal/syscall/unix/nonblocking_wasi.go b/src/internal/syscall/unix/nonblocking_wasi.go new file mode 100644 index 0000000000000..ff67c75e81a02 --- /dev/null +++ b/src/internal/syscall/unix/nonblocking_wasi.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +func IsNonblock(fd int) (nonblocking bool, err error) { + return false, nil +} diff --git a/src/mime/type_unix.go b/src/mime/type_unix.go index 0b247b623a748..e1876655b3b02 100644 --- a/src/mime/type_unix.go +++ b/src/mime/type_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package mime diff --git a/src/net/error_posix.go b/src/net/error_posix.go index d709a273b73cf..e3e79a851f04a 100644 --- a/src/net/error_posix.go +++ b/src/net/error_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package net diff --git a/src/net/error_unix.go b/src/net/error_unix.go index e6153303882fe..40fa02a1d33a8 100644 --- a/src/net/error_unix.go +++ b/src/net/error_unix.go @@ -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 aix darwin dragonfly freebsd js linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js linux netbsd openbsd solaris wasi package net diff --git a/src/net/file_stub.go b/src/net/file_stub.go index bfb8100f53cf0..26e3cf7ff3047 100644 --- a/src/net/file_stub.go +++ b/src/net/file_stub.go @@ -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 js,wasm +// +build js,wasm wasi package net diff --git a/src/net/hook_unix.go b/src/net/hook_unix.go index a28f1e066dad4..ac3e01ff6e6d6 100644 --- a/src/net/hook_unix.go +++ b/src/net/hook_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package net diff --git a/src/net/http/roundtrip.go b/src/net/http/roundtrip.go index 2ec736bfb1975..2a1df1e87a8f9 100644 --- a/src/net/http/roundtrip.go +++ b/src/net/http/roundtrip.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !js !wasm - package http // RoundTrip implements the RoundTripper interface. diff --git a/src/net/interface_stub.go b/src/net/interface_stub.go index ec58665e195db..3f05dc9ce9ee9 100644 --- a/src/net/interface_stub.go +++ b/src/net/interface_stub.go @@ -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 js,wasm +// +build js,wasm wasi package net diff --git a/src/net/internal/socktest/switch_unix.go b/src/net/internal/socktest/switch_unix.go index 7dc35184105bb..6fe914aa35f8f 100644 --- a/src/net/internal/socktest/switch_unix.go +++ b/src/net/internal/socktest/switch_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package socktest diff --git a/src/net/internal/socktest/sys_unix.go b/src/net/internal/socktest/sys_unix.go index 0525512bff953..8fe5c1ad708a6 100644 --- a/src/net/internal/socktest/sys_unix.go +++ b/src/net/internal/socktest/sys_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package socktest diff --git a/src/net/iprawsock_posix.go b/src/net/iprawsock_posix.go index e653f6ae17b08..0a42471ef0784 100644 --- a/src/net/iprawsock_posix.go +++ b/src/net/iprawsock_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package net diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index 8763d579fb18b..aa202c81b7531 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package net diff --git a/src/net/lookup_fake.go b/src/net/lookup_fake.go index 3b3c39bc7dacf..ea2bda194b80b 100644 --- a/src/net/lookup_fake.go +++ b/src/net/lookup_fake.go @@ -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 js,wasm +// +build js,wasm wasi package net diff --git a/src/net/main_noconf_test.go b/src/net/main_noconf_test.go index bac84aa3002ab..fecb23334d544 100644 --- a/src/net/main_noconf_test.go +++ b/src/net/main_noconf_test.go @@ -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 js,wasm plan9 windows +// +build js,wasm plan9 wasi windows package net diff --git a/src/net/net_fake.go b/src/net/net_fake.go index 0c48dd5c03bb4..1007ed0c5d176 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -4,7 +4,7 @@ // Fake networking for js/wasm. It is intended to allow tests of other package to pass. -// +build js,wasm +// +build js,wasm wasi package net diff --git a/src/net/port_unix.go b/src/net/port_unix.go index 4fdd9a37bc673..47aacc856409e 100644 --- a/src/net/port_unix.go +++ b/src/net/port_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi // Read system port mappings from /etc/services diff --git a/src/net/rawconn_stub_test.go b/src/net/rawconn_stub_test.go index cec977f75d9e2..0e3f4c596ce9e 100644 --- a/src/net/rawconn_stub_test.go +++ b/src/net/rawconn_stub_test.go @@ -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 js,wasm plan9 +// +build js,wasm plan9 wasi package net diff --git a/src/net/sendfile_stub.go b/src/net/sendfile_stub.go index 53bc53af43b09..6614648044f49 100644 --- a/src/net/sendfile_stub.go +++ b/src/net/sendfile_stub.go @@ -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 aix darwin js,wasm netbsd openbsd +// +build aix darwin js,wasm netbsd openbsd wasi package net diff --git a/src/net/sock_stub.go b/src/net/sock_stub.go index c9f86af4e7c5c..184f142ac65fc 100644 --- a/src/net/sock_stub.go +++ b/src/net/sock_stub.go @@ -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 aix js,wasm solaris +// +build aix js,wasm solaris wasi package net diff --git a/src/net/sockaddr_posix.go b/src/net/sockaddr_posix.go index a3710dd3f749f..6b9bc5fd0f797 100644 --- a/src/net/sockaddr_posix.go +++ b/src/net/sockaddr_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows wasi package net diff --git a/src/net/sockopt_stub.go b/src/net/sockopt_stub.go index 52624a35d81b8..1834cc5bdfdf4 100644 --- a/src/net/sockopt_stub.go +++ b/src/net/sockopt_stub.go @@ -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 js,wasm +// +build js,wasm wasi package net diff --git a/src/net/sockoptip_stub.go b/src/net/sockoptip_stub.go index 57cd2890405c0..497bc17db225f 100644 --- a/src/net/sockoptip_stub.go +++ b/src/net/sockoptip_stub.go @@ -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 js,wasm +// +build js,wasm wasi package net diff --git a/src/net/tcpsock_posix.go b/src/net/tcpsock_posix.go index 257c11976f46b..41d75bac696ac 100644 --- a/src/net/tcpsock_posix.go +++ b/src/net/tcpsock_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows wasi package net diff --git a/src/net/tcpsockopt_stub.go b/src/net/tcpsockopt_stub.go index d043da123d6e8..da0974dee35de 100644 --- a/src/net/tcpsockopt_stub.go +++ b/src/net/tcpsockopt_stub.go @@ -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 js,wasm +// +build js,wasm wasi package net diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index bbfa4ed9c73af..4d98d36ebe6f1 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows wasi package net diff --git a/src/net/unixsock_posix.go b/src/net/unixsock_posix.go index 275c7c936d11c..068881dc42eaf 100644 --- a/src/net/unixsock_posix.go +++ b/src/net/unixsock_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows wasi package net diff --git a/src/os/dir_wasi.go b/src/os/dir_wasi.go new file mode 100644 index 0000000000000..fd522c71bf4c9 --- /dev/null +++ b/src/os/dir_wasi.go @@ -0,0 +1,97 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package os + +import ( + "io" + "runtime" + "syscall" +) + +// Auxiliary information if the File describes a directory +type dirInfo struct { + buf []byte // buffer for directory I/O + data []byte // unread portion of buf + cookie syscall.Dircookie_t // pointer to next directory entry +} + +const ( + // More than 5760 to work around https://golang.org/issue/24015. + blockSize = 8192 +) + +func (d *dirInfo) close() {} + +func (f *File) seekInvalidate() {} + +func (f *File) readdirnames(n int) (names []string, err error) { + d := f.dirinfo + if d == nil { + d = &dirInfo{ + buf: make([]byte, blockSize), + } + f.dirinfo = d + } + + size := n + if size <= 0 { + size = 100 + n = -1 + } + + names = make([]string, 0, size) + for n != 0 { + done := false + if len(d.data) == 0 { + n, err := f.pfd.ReadDir(d.buf, d.cookie) + done = n < len(d.buf) + d.data = d.buf[:n] + runtime.KeepAlive(f) + if err != nil { + return names, wrapSyscallError("readdirnames", err) + } + } + + for n != 0 { + if len(d.data) < 24 { + d.data = nil + break // incomplete dirent + } + namelen := readUint32(d.data[16:]) + if len(d.data) < int(24+namelen) { + d.data = nil + break // incomplete name + } + d.cookie = syscall.Dircookie_t(readUint64(d.data[0:])) + name := string(d.data[24 : 24+namelen]) + d.data = d.data[24+namelen:] + if name == "." || name == ".." { + continue + } + names = append(names, name) + n-- + } + + if done { + break + } + } + + if n >= 0 && len(names) == 0 { + return names, io.EOF + } + return names, nil +} + +func readUint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func readUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} diff --git a/src/os/error_posix.go b/src/os/error_posix.go index 2aeca8230439e..c78a97a162caf 100644 --- a/src/os/error_posix.go +++ b/src/os/error_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows wasi package os diff --git a/src/os/error_unix_test.go b/src/os/error_unix_test.go index bfc83c98673d8..b61b7b490c90f 100644 --- a/src/os/error_unix_test.go +++ b/src/os/error_unix_test.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package os_test diff --git a/src/os/exec/lp_wasi.go b/src/os/exec/lp_wasi.go new file mode 100644 index 0000000000000..4e3af8ce420d8 --- /dev/null +++ b/src/os/exec/lp_wasi.go @@ -0,0 +1,21 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package exec + +import ( + "errors" +) + +// ErrNotFound is the error resulting if a path search failed to find an executable file. +var ErrNotFound = errors.New("executable file not found in $PATH") + +// LookPath searches for an executable named file in the +// directories named by the PATH environment variable. +// If file contains a slash, it is tried directly and the PATH is not consulted. +// The result may be an absolute path or a path relative to the current directory. +func LookPath(file string) (string, error) { + // Wasm can not execute processes, so act as if there are no executables at all. + return "", &Error{file, ErrNotFound} +} diff --git a/src/os/exec_posix.go b/src/os/exec_posix.go index 45b47a542d6a9..df916026f378a 100644 --- a/src/os/exec_posix.go +++ b/src/os/exec_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows wasi package os diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go index 6e4ffe82d2676..d2c72093d24a5 100644 --- a/src/os/exec_unix.go +++ b/src/os/exec_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package os diff --git a/src/os/executable_procfs.go b/src/os/executable_procfs.go index 2628223b8db84..e5a5e73f51c73 100644 --- a/src/os/executable_procfs.go +++ b/src/os/executable_procfs.go @@ -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 linux netbsd dragonfly js,wasm +// +build linux netbsd dragonfly js,wasm wasi package os diff --git a/src/os/export_unix_test.go b/src/os/export_unix_test.go index 39866a68deb8d..0995d88607586 100644 --- a/src/os/export_unix_test.go +++ b/src/os/export_unix_test.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package os diff --git a/src/os/file_posix.go b/src/os/file_posix.go index c3635ddd289bd..316d54167a2b9 100644 --- a/src/os/file_posix.go +++ b/src/os/file_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package os diff --git a/src/os/file_unix.go b/src/os/file_unix.go index 32e4442e5d067..e226e23aa1822 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package os @@ -122,36 +122,6 @@ func newFile(fd uintptr, name string, kind newFileKind) *File { pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock - // If the caller passed a non-blocking filedes (kindNonBlock), - // we assume they know what they are doing so we allow it to be - // used with kqueue. - if kind == kindOpenFile { - switch runtime.GOOS { - case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd": - var st syscall.Stat_t - err := syscall.Fstat(fdi, &st) - typ := st.Mode & syscall.S_IFMT - // Don't try to use kqueue with regular files on *BSDs. - // On FreeBSD a regular file is always - // reported as ready for writing. - // On Dragonfly, NetBSD and OpenBSD the fd is signaled - // only once as ready (both read and write). - // Issue 19093. - // Also don't add directories to the netpoller. - if err == nil && (typ == syscall.S_IFREG || typ == syscall.S_IFDIR) { - pollable = false - } - - // In addition to the behavior described above for regular files, - // on Darwin, kqueue does not work properly with fifos: - // closing the last writer does not cause a kqueue event - // for any readers. See issue #24164. - if runtime.GOOS == "darwin" && typ == syscall.S_IFIFO { - pollable = false - } - } - } - if err := f.pfd.Init("file", pollable); err != nil { // An error here indicates a failure to register // with the netpoll system. That can happen for diff --git a/src/os/os_test.go b/src/os/os_test.go index 44e1434dbe795..b8f36001e95ac 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1102,8 +1102,8 @@ func checkMode(t *testing.T, path string, mode FileMode) { func TestChmod(t *testing.T) { // Chmod is not supported under windows. - if runtime.GOOS == "windows" { - return + if runtime.GOOS == "windows" || runtime.GOOS == "wasi" { + t.Skip("Chmod is not supported on " + runtime.GOOS) } f := newFile("TestChmod", t) defer Remove(f.Name()) @@ -1973,6 +1973,10 @@ func TestLargeWriteToConsole(t *testing.T) { } func TestStatDirModeExec(t *testing.T) { + if runtime.GOOS == "wasi" { + t.Skip("Chmod is not supported on " + runtime.GOOS) + } + const mode = 0111 path, err := ioutil.TempDir("", "go-build") @@ -2168,9 +2172,11 @@ func TestLongPath(t *testing.T) { if dir.Size() != filesize || filesize != wantSize { t.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path, dir.Size(), filesize, wantSize) } - err = Chmod(path, dir.Mode()) - if err != nil { - t.Fatalf("Chmod(%q) failed: %v", path, err) + if runtime.GOOS != "wasi" { // Chmod is not supported on wasi + err = Chmod(path, dir.Mode()) + if err != nil { + t.Fatalf("Chmod(%q) failed: %v", path, err) + } } } if err := Truncate(sizedTempDir+"/bar.txt", 0); err != nil { diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 45cb6fc21f2ee..18bb7e14e5530 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package os_test diff --git a/src/os/path_unix.go b/src/os/path_unix.go index c99a8240c531b..42efffe23e4d5 100644 --- a/src/os/path_unix.go +++ b/src/os/path_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package os diff --git a/src/os/pipe_bsd.go b/src/os/pipe_bsd.go index 0d2d82feb9519..01d9797605c61 100644 --- a/src/os/pipe_bsd.go +++ b/src/os/pipe_bsd.go @@ -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 aix darwin dragonfly js,wasm solaris +// +build aix darwin dragonfly js,wasm solaris wasi package os diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go index 2e93e3946af84..424bbe6dbd271 100644 --- a/src/os/pipe_test.go +++ b/src/os/pipe_test.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Test broken pipes on Unix systems. -// +build !plan9,!js +// +build !plan9,!js,!wasi package os_test diff --git a/src/os/rawconn_test.go b/src/os/rawconn_test.go index 2554f5b087846..8ecf409c2071e 100644 --- a/src/os/rawconn_test.go +++ b/src/os/rawconn_test.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Test use of raw connections. -// +build !plan9,!js +// +build !plan9,!js,!wasi package os_test diff --git a/src/os/removeall_test.go b/src/os/removeall_test.go index 8a71f687ed0d7..92473abd66388 100644 --- a/src/os/removeall_test.go +++ b/src/os/removeall_test.go @@ -80,8 +80,8 @@ func TestRemoveAll(t *testing.T) { t.Fatalf("Lstat %q succeeded after RemoveAll (third)", path) } - // Chmod is not supported under Windows and test fails as root. - if runtime.GOOS != "windows" && Getuid() != 0 { + // Chmod is not supported under Windows and wasi and test fails as root. + if runtime.GOOS != "windows" && runtime.GOOS != "wasi" && Getuid() != 0 { // Make directory with file and subdirectory and trigger error. if err = MkdirAll(dpath, 0777); err != nil { t.Fatalf("MkdirAll %q: %s", dpath, err) diff --git a/src/os/signal/signal_unix.go b/src/os/signal/signal_unix.go index 89ee2d9e18569..abd33bcd35df1 100644 --- a/src/os/signal/signal_unix.go +++ b/src/os/signal/signal_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package signal diff --git a/src/os/stat_unix.go b/src/os/stat_unix.go index 0a7e6029ac234..47ab5269f6a13 100644 --- a/src/os/stat_unix.go +++ b/src/os/stat_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package os diff --git a/src/os/stat_wasi.go b/src/os/stat_wasi.go new file mode 100644 index 0000000000000..517c194e93d84 --- /dev/null +++ b/src/os/stat_wasi.go @@ -0,0 +1,37 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package os + +import ( + "syscall" + "time" +) + +func fillFileStatFromSys(fs *fileStat, name string) { + fs.name = basename(name) + fs.size = int64(fs.sys.Size) + fs.modTime = time.Unix(0, int64(fs.sys.Mtime)) + + switch fs.sys.Filetype { + case syscall.FILETYPE_BLOCK_DEVICE: + fs.mode |= ModeDevice + case syscall.FILETYPE_CHARACTER_DEVICE: + fs.mode |= ModeDevice | ModeCharDevice + case syscall.FILETYPE_DIRECTORY: + fs.mode |= ModeDir + case syscall.FILETYPE_SOCKET_DGRAM: + fs.mode |= ModeSocket + case syscall.FILETYPE_SOCKET_STREAM: + fs.mode |= ModeSocket + case syscall.FILETYPE_SYMBOLIC_LINK: + fs.mode |= ModeSymlink + } +} + +// For testing. +func atime(fi FileInfo) time.Time { + st := fi.Sys().(*syscall.Stat_t) + return time.Unix(0, int64(st.Atime)) +} diff --git a/src/os/sticky_bsd.go b/src/os/sticky_bsd.go index c09b1ac202889..d31c0521f1834 100644 --- a/src/os/sticky_bsd.go +++ b/src/os/sticky_bsd.go @@ -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 aix darwin dragonfly freebsd js,wasm netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm netbsd openbsd solaris wasi package os diff --git a/src/os/sticky_notbsd.go b/src/os/sticky_notbsd.go index c15850692cd75..f37849144d4b2 100644 --- a/src/os/sticky_notbsd.go +++ b/src/os/sticky_notbsd.go @@ -10,6 +10,7 @@ // +build !netbsd // +build !openbsd // +build !solaris +// +build !wasi package os diff --git a/src/os/sys_bsd.go b/src/os/sys_bsd.go index b1698f5d4c763..fbf655610b6eb 100644 --- a/src/os/sys_bsd.go +++ b/src/os/sys_bsd.go @@ -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 darwin dragonfly freebsd js,wasm netbsd openbsd +// +build darwin dragonfly freebsd js,wasm netbsd openbsd wasi package os diff --git a/src/os/sys_wasi.go b/src/os/sys_wasi.go new file mode 100644 index 0000000000000..09ec58a7cbc6a --- /dev/null +++ b/src/os/sys_wasi.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package os + +// supportsCloseOnExec reports whether the platform supports the +// O_CLOEXEC flag. +const supportsCloseOnExec = false diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go index 0fe03fa517f43..8908003335e3c 100644 --- a/src/os/timeout_test.go +++ b/src/os/timeout_test.go @@ -4,6 +4,7 @@ // +build !js // +build !plan9 +// +build !wasi // +build !windows package os_test diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go index 0890cd8f2bf0f..4529a705193ec 100644 --- a/src/os/user/lookup_unix.go +++ b/src/os/user/lookup_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm !android,linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm !android,linux netbsd openbsd solaris wasi // +build !cgo osusergo package user diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go index 0f4cdc4533909..a9e99625d8e65 100644 --- a/src/os/wait_unimp.go +++ b/src/os/wait_unimp.go @@ -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 aix darwin dragonfly js,wasm netbsd openbsd solaris +// +build aix darwin dragonfly js,wasm netbsd openbsd solaris wasi package os diff --git a/src/path/filepath/path_unix.go b/src/path/filepath/path_unix.go index ec497d9e26bb8..359e889d3908e 100644 --- a/src/path/filepath/path_unix.go +++ b/src/path/filepath/path_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package filepath diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index 7d88beb537dcf..1d466655476b8 100644 --- a/src/runtime/asm_wasm.s +++ b/src/runtime/asm_wasm.s @@ -15,7 +15,6 @@ TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME, $0 // set g to g0 MOVD $runtime·g0(SB), g CALLNORESUME runtime·check(SB) - CALLNORESUME runtime·args(SB) CALLNORESUME runtime·osinit(SB) CALLNORESUME runtime·schedinit(SB) MOVD $0, 0(SP) diff --git a/src/runtime/crash_nonunix_test.go b/src/runtime/crash_nonunix_test.go index 06c197ec2b238..c171a34023a96 100644 --- a/src/runtime/crash_nonunix_test.go +++ b/src/runtime/crash_nonunix_test.go @@ -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 windows plan9 js,wasm +// +build windows plan9 js,wasm wasi package runtime_test diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go index f95ff68545078..22e68f925a907 100644 --- a/src/runtime/env_posix.go +++ b/src/runtime/env_posix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package runtime diff --git a/src/runtime/lock_wasi.go b/src/runtime/lock_wasi.go new file mode 100644 index 0000000000000..0b7272b91d16f --- /dev/null +++ b/src/runtime/lock_wasi.go @@ -0,0 +1,92 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +// js/wasm has no support for threads yet. There is no preemption. +// Waiting for a mutex or timeout is implemented as a busy loop +// while allowing other goroutines to run. + +const ( + mutex_unlocked = 0 + mutex_locked = 1 + + active_spin = 4 + active_spin_cnt = 30 + passive_spin = 1 +) + +func lock(l *mutex) { + for l.key == mutex_locked { + Gosched() + } + gp := getg() + if gp.m.locks < 0 { + throw("lock count") + } + gp.m.locks++ + l.key = mutex_locked +} + +func unlock(l *mutex) { + if l.key == mutex_unlocked { + throw("unlock of unlocked lock") + } + gp := getg() + gp.m.locks-- + if gp.m.locks < 0 { + throw("lock count") + } + l.key = mutex_unlocked +} + +// One-time notifications. +func noteclear(n *note) { + n.key = 0 +} + +func notewakeup(n *note) { + if n.key != 0 { + print("notewakeup - double wakeup (", n.key, ")\n") + throw("notewakeup - double wakeup") + } + n.key = 1 +} + +func notesleep(n *note) { + throw("notesleep not supported by js") +} + +func notetsleep(n *note, ns int64) bool { + throw("notetsleep not supported by js") + return false +} + +// same as runtime·notetsleep, but called on user g (not g0) +func notetsleepg(n *note, ns int64) bool { + gp := getg() + if gp == gp.m.g0 { + throw("notetsleepg on g0") + } + + deadline := nanotime() + ns + for { + if n.key != 0 { + return true + } + if __wasi_sched_yield() != 0 { + throw("__wasi_sched_yield failed") + } + Gosched() + if ns >= 0 && nanotime() >= deadline { + return false + } + } +} + +func beforeIdle(delay int64) bool { + return false +} + +func checkTimeouts() {} diff --git a/src/runtime/mem_wasi.go b/src/runtime/mem_wasi.go new file mode 100644 index 0000000000000..944dc8d7fb3c2 --- /dev/null +++ b/src/runtime/mem_wasi.go @@ -0,0 +1,75 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "runtime/internal/sys" + "unsafe" +) + +// Don't split the stack as this function may be invoked without a valid G, +// which prevents us from allocating more stack. +//go:nosplit +func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer { + p := sysReserve(nil, n) + sysMap(p, n, sysStat) + return p +} + +func sysUnused(v unsafe.Pointer, n uintptr) { +} + +func sysUsed(v unsafe.Pointer, n uintptr) { +} + +func sysHugePage(v unsafe.Pointer, n uintptr) { +} + +// Don't split the stack as this function may be invoked without a valid G, +// which prevents us from allocating more stack. +//go:nosplit +func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) { + mSysStatDec(sysStat, n) +} + +func sysFault(v unsafe.Pointer, n uintptr) { +} + +var reserveEnd uintptr + +func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer { + // TODO(neelance): maybe unify with mem_plan9.go, depending on how https://github.com/WebAssembly/design/blob/master/FutureFeatures.md#finer-grained-control-over-memory turns out + + if v != nil { + // The address space of WebAssembly's linear memory is contiguous, + // so requesting specific addresses is not supported. We could use + // a different address, but then mheap.sysAlloc discards the result + // right away and we don't reuse chunks passed to sysFree. + return nil + } + + if reserveEnd < lastmoduledatap.end { + reserveEnd = lastmoduledatap.end + } + v = unsafe.Pointer(reserveEnd) + reserveEnd += n + + current := currentMemory() + needed := int32(reserveEnd/sys.DefaultPhysPageSize + 1) + if current < needed { + if growMemory(needed-current) == -1 { + return nil + } + } + + return v +} + +func currentMemory() int32 +func growMemory(pages int32) int32 + +func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) { + mSysStatInc(sysStat, n) +} diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go index 25b1d5d49efdc..fd239e8fb89af 100644 --- a/src/runtime/netpoll.go +++ b/src/runtime/netpoll.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi windows package runtime diff --git a/src/runtime/netpoll_fake.go b/src/runtime/netpoll_fake.go index b2af3b89b2c51..559fd86db994f 100644 --- a/src/runtime/netpoll_fake.go +++ b/src/runtime/netpoll_fake.go @@ -5,7 +5,7 @@ // Fake network poller for wasm/js. // Should never be used, because wasm/js network connections do not honor "SetNonblock". -// +build js,wasm +// +build js,wasm wasi package runtime diff --git a/src/runtime/os_wasi.go b/src/runtime/os_wasi.go new file mode 100644 index 0000000000000..6258b182de55b --- /dev/null +++ b/src/runtime/os_wasi.go @@ -0,0 +1,295 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "unsafe" +) + +type uintptr_t uint32 +type size_t uint32 +type __wasi_errno_t uint32 +type __wasi_clockid_t uint32 +type __wasi_timestamp_t uint64 +type __wasi_fd_t uint32 + +const ( + __WASI_CLOCK_REALTIME __wasi_clockid_t = 0 + __WASI_CLOCK_MONOTONIC __wasi_clockid_t = 1 + __WASI_CLOCK_PROCESS_CPUTIME_ID __wasi_clockid_t = 2 + __WASI_CLOCK_THREAD_CPUTIME_ID __wasi_clockid_t = 3 +) + +type __wasi_ciovec_t struct { + buf uintptr_t + buf_len size_t +} + +//go:wasmimport __wasi_args_get wasi_unstable args_get +func __wasi_args_get( + argv *uintptr_t, + argv_buf *byte, +) __wasi_errno_t + +//go:wasmimport __wasi_args_sizes_get wasi_unstable args_sizes_get +func __wasi_args_sizes_get( + argc *size_t, + argv_buf_size *size_t, +) __wasi_errno_t + +//go:wasmimport __wasi_clock_time_get wasi_unstable clock_time_get +func __wasi_clock_time_get( + clock_id __wasi_clockid_t, + precision __wasi_timestamp_t, + time *__wasi_timestamp_t, +) __wasi_errno_t + +//go:wasmimport __wasi_environ_get wasi_unstable environ_get +func __wasi_environ_get( + environ *uintptr_t, + environ_buf *byte, +) __wasi_errno_t + +//go:wasmimport __wasi_environ_sizes_get wasi_unstable environ_sizes_get +func __wasi_environ_sizes_get( + environ_count *size_t, + environ_buf_size *size_t, +) __wasi_errno_t + +//go:wasmimport __wasi_proc_exit wasi_unstable proc_exit +func __wasi_proc_exit( + code int32, +) + +//go:wasmimport __wasi_fd_write wasi_unstable fd_write +func __wasi_fd_write( + fd __wasi_fd_t, + iovs *__wasi_ciovec_t, + iovs_len size_t, + nwritten *size_t, +) __wasi_errno_t + +//go:wasmimport __wasi_sched_yield wasi_unstable sched_yield +func __wasi_sched_yield() __wasi_errno_t + +//go:wasmimport __wasi_random_get wasi_unstable random_get +func __wasi_random_get( + buf *byte, + buf_len size_t, +) __wasi_errno_t + +func exit(code int32) { + __wasi_proc_exit(code) +} + +func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { + if fd > 2 { + throw("runtime.write to fd > 2 is unsupported") + } + iov := __wasi_ciovec_t{ + buf: uintptr_t(uintptr(p)), + buf_len: size_t(n), + } + var nwritten size_t + if __wasi_fd_write(__wasi_fd_t(fd), &iov, 1, &nwritten) != 0 { + throw("__wasi_fd_write failed") + } + return int32(nwritten) +} + +// Stubs so tests can link correctly. These should never be called. +func open(name *byte, mode, perm int32) int32 { panic("not implemented") } +func closefd(fd int32) int32 { panic("not implemented") } +func read(fd int32, p unsafe.Pointer, n int32) int32 { panic("not implemented") } + +func usleep(usec uint32) + +func exitThread(wait *uint32) + +type mOS struct{} + +func osyield() + +const _SIGSEGV = 0xb + +func sigpanic() { + g := getg() + if !canpanic(g) { + throw("unexpected signal during runtime execution") + } + + // js only invokes the exception handler for memory faults. + g.sig = _SIGSEGV + panicmem() +} + +type sigset struct{} + +// Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +func mpreinit(mp *m) { + mp.gsignal = malg(32 * 1024) + mp.gsignal.m = mp +} + +//go:nosplit +func msigsave(mp *m) { +} + +//go:nosplit +func msigrestore(sigmask sigset) { +} + +//go:nosplit +//go:nowritebarrierrec +func clearSignalHandlers() { +} + +//go:nosplit +func sigblock() { +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, cannot allocate memory. +func minit() { +} + +// Called from dropm to undo the effect of an minit. +func unminit() { +} + +func osinit() { + ncpu = 1 + getg().m.procid = 2 + physPageSize = 64 * 1024 +} + +// wasm has no signals +const _NSIG = 0 + +func signame(sig uint32) string { + return "" +} + +func crash() { + *(*int32)(nil) = 0 +} + +func getRandomData(r []byte) { + if __wasi_random_get(&r[0], size_t(len(r))) != 0 { + throw("__wasi_random_get failed") + } +} + +func goenvs() { + // arguments + var argc size_t + var argv_buf_size size_t + if __wasi_args_sizes_get(&argc, &argv_buf_size) != 0 { + throw("__wasi_args_sizes_get failed") + } + + argslice = make([]string, argc) + if argc > 0 { + argv := make([]uintptr_t, argc) + argv_buf := make([]byte, argv_buf_size) + if __wasi_args_get(&argv[0], &argv_buf[0]) != 0 { + throw("__wasi_args_get failed") + } + + for i := range argslice { + start := argv[i] - uintptr_t(uintptr(unsafe.Pointer(&argv_buf[0]))) + end := start + for argv_buf[end] != 0 { + end++ + } + argslice[i] = string(argv_buf[start:end]) + } + } + + // environment + var environ_count size_t + var environ_buf_size size_t + if __wasi_environ_sizes_get(&environ_count, &environ_buf_size) != 0 { + throw("__wasi_environ_sizes_get failed") + } + + envs = make([]string, environ_count) + if environ_count > 0 { + environ := make([]uintptr_t, environ_count) + environ_buf := make([]byte, environ_buf_size) + if __wasi_environ_get(&environ[0], &environ_buf[0]) != 0 { + throw("__wasi_environ_get failed") + } + + for i := range envs { + start := environ[i] - uintptr_t(uintptr(unsafe.Pointer(&environ_buf[0]))) + end := start + for environ_buf[end] != 0 { + end++ + } + envs[i] = string(environ_buf[start:end]) + } + } +} + +func walltime1() (sec int64, nsec int32) { + var time __wasi_timestamp_t + if __wasi_clock_time_get(__WASI_CLOCK_REALTIME, 0, &time) != 0 { + throw("__wasi_clock_time_get failed") + } + return int64(time / 1000000000), int32(time % 1000000000) +} + +func nanotime1() int64 { + var time __wasi_timestamp_t + if __wasi_clock_time_get(__WASI_CLOCK_MONOTONIC, 0, &time) != 0 { + throw("__wasi_clock_time_get failed") + } + return int64(time) +} + +func initsig(preinit bool) { +} + +// May run with m.p==nil, so write barriers are not allowed. +//go:nowritebarrier +func newosproc(mp *m) { + panic("newosproc: not implemented") +} + +func setProcessCPUProfiler(hz int32) {} +func setThreadCPUProfiler(hz int32) {} +func sigdisable(uint32) {} +func sigenable(uint32) {} +func sigignore(uint32) {} + +//go:linkname os_sigpipe os.sigpipe +func os_sigpipe() { + throw("too many writes on closed pipe") +} + +//go:nosplit +func cputicks() int64 { + // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand(). + // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. + // TODO: need more entropy to better seed fastrand. + return nanotime() +} + +//go:linkname syscall_now syscall.now +func syscall_now() (sec int64, nsec int32) { + sec, nsec, _ = time_now() + return +} + +// gsignalStack is unused on js. +type gsignalStack struct{} + +const preemptMSupported = false + +func preemptM(mp *m) { + // No threads, so nothing to do. +} diff --git a/src/runtime/rt0_wasi_wasm.s b/src/runtime/rt0_wasi_wasm.s new file mode 100644 index 0000000000000..b53672a97159c --- /dev/null +++ b/src/runtime/rt0_wasi_wasm.s @@ -0,0 +1,55 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go_asm.h" +#include "textflag.h" + +TEXT _rt0_wasm_wasi(SB),NOSPLIT,$0 + MOVD $runtime·wasmStack+m0Stack__size(SB), SP + + I32Const $0 // entry PC_B + Call runtime·rt0_go(SB) + Drop + Call wasm_pc_f_loop(SB) + + Return + +TEXT wasm_pc_f_loop(SB),NOSPLIT,$0 +// Call the function for the current PC_F. Repeat until PAUSE != 0 indicates pause or exit. +// The WebAssembly stack may unwind, e.g. when switching goroutines. +// The Go stack on the linear memory is then used to jump to the correct functions +// with this loop, without having to restore the full WebAssembly stack. +// It is expected to have a pending call before entering the loop, so check PAUSE first. + Get PAUSE + I32Eqz + If + loop: + Loop + // Get PC_B & PC_F from -8(SP) + Get SP + I32Const $8 + I32Sub + I32Load16U $0 // PC_B + + Get SP + I32Const $8 + I32Sub + I32Load16U $2 // PC_F + + CallIndirect $0 + Drop + + Get PAUSE + I32Eqz + BrIf loop + End + End + + I32Const $0 + Set PAUSE + + Return + +TEXT wasm_export_lib(SB),NOSPLIT,$0 + UNDEF diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go index 4a1a5cc3d90bb..42be16d85b4db 100644 --- a/src/runtime/stubs2.go +++ b/src/runtime/stubs2.go @@ -6,6 +6,7 @@ // +build !solaris // +build !windows // +build !js +// +build !wasi // +build !darwin // +build !aix diff --git a/src/runtime/stubs3.go b/src/runtime/stubs3.go index 2e576c2b6d03a..b8d847ba6f106 100644 --- a/src/runtime/stubs3.go +++ b/src/runtime/stubs3.go @@ -7,6 +7,8 @@ // +build !freebsd // +build !darwin // +build !aix +// +build !js +// +build !wasi package runtime diff --git a/src/runtime/sys_wasm.go b/src/runtime/sys_wasm.go index 0e88bdefc7198..4a8187b7b2af3 100644 --- a/src/runtime/sys_wasm.go +++ b/src/runtime/sys_wasm.go @@ -24,9 +24,6 @@ func wasmDiv() func wasmTruncS() func wasmTruncU() -//go:wasmimport wasmExit go runtime.wasmExit abi0 -func wasmExit(code int32) - // adjust Gobuf as it if executed a call to fn with context ctxt // and then did an immediate gosave. func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) { diff --git a/src/runtime/timestub2.go b/src/runtime/timestub2.go index 7f471e0e1029c..e3e5094db9c1a 100644 --- a/src/runtime/timestub2.go +++ b/src/runtime/timestub2.go @@ -7,6 +7,7 @@ // +build !freebsd // +build !aix // +build !solaris +// +build !wasi package runtime diff --git a/src/syscall/dirent.go b/src/syscall/dirent.go index fab123d4a7d8b..2b8f8aa6c4567 100644 --- a/src/syscall/dirent.go +++ b/src/syscall/dirent.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package syscall diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go index e80a3ff1c9687..113f0d585ce47 100644 --- a/src/syscall/env_unix.go +++ b/src/syscall/env_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi // Unix environment variables. diff --git a/src/syscall/fs_wasi.go b/src/syscall/fs_wasi.go new file mode 100644 index 0000000000000..0bb37475bd402 --- /dev/null +++ b/src/syscall/fs_wasi.go @@ -0,0 +1,698 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +import ( + "io" + "strings" + "sync" + "unsafe" +) + +type uintptr_t uint32 +type size_t uint32 + +type Device_t uint64 +type Fd_t uint32 +type Fdflags_t uint32 +type Filesize_t uint64 +type Filetype_t uint8 +type Inode_t uint64 +type Linkcount_t uint32 +type Lookupflags_t uint32 +type Oflags_t uint32 +type Rights_t uint64 +type Timestamp_t uint64 +type Dircookie_t uint64 +type Filedelta_t int64 +type Whence_t uint32 +type Fstflags_t uint32 + +type Ciovec_t struct { + buf uintptr_t + buf_len size_t +} + +type Stat_t struct { + Dev Device_t + Ino Inode_t + Filetype Filetype_t + Nlink Linkcount_t + Size Filesize_t + Atime Timestamp_t + Mtime Timestamp_t + Ctime Timestamp_t +} + +type Fdstat_t struct { + Filetype Filetype_t + Flags Fdflags_t + RightsBase Rights_t + RightsInheriting Rights_t +} + +const ( + LOOKUP_SYMLINK_FOLLOW Lookupflags_t = 0x00000001 + + OFLAG_CREATE Oflags_t = 0x0001 + OFLAG_DIRECTORY Oflags_t = 0x0002 + OFLAG_EXCL Oflags_t = 0x0004 + OFLAG_TRUNC Oflags_t = 0x0008 + + FDFLAG_APPEND Fdflags_t = 0x0001 + FDFLAG_DSYNC Fdflags_t = 0x0002 + FDFLAG_NONBLOCK Fdflags_t = 0x0004 + FDFLAG_RSYNC Fdflags_t = 0x0008 + FDFLAG_SYNC Fdflags_t = 0x0010 + + RIGHT_FD_DATASYNC Rights_t = 0x0000000000000001 + RIGHT_FD_READ Rights_t = 0x0000000000000002 + RIGHT_FD_SEEK Rights_t = 0x0000000000000004 + RIGHT_FD_FDSTAT_SET_FLAGS Rights_t = 0x0000000000000008 + RIGHT_FD_SYNC Rights_t = 0x0000000000000010 + RIGHT_FD_TELL Rights_t = 0x0000000000000020 + RIGHT_FD_WRITE Rights_t = 0x0000000000000040 + RIGHT_FD_ADVISE Rights_t = 0x0000000000000080 + RIGHT_FD_ALLOCATE Rights_t = 0x0000000000000100 + RIGHT_PATH_CREATE_DIRECTORY Rights_t = 0x0000000000000200 + RIGHT_PATH_CREATE_FILE Rights_t = 0x0000000000000400 + RIGHT_PATH_LINK_SOURCE Rights_t = 0x0000000000000800 + RIGHT_PATH_LINK_TARGET Rights_t = 0x0000000000001000 + RIGHT_PATH_OPEN Rights_t = 0x0000000000002000 + RIGHT_FD_READDIR Rights_t = 0x0000000000004000 + RIGHT_PATH_READLINK Rights_t = 0x0000000000008000 + RIGHT_PATH_RENAME_SOURCE Rights_t = 0x0000000000010000 + RIGHT_PATH_RENAME_TARGET Rights_t = 0x0000000000020000 + RIGHT_PATH_FILESTAT_GET Rights_t = 0x0000000000040000 + RIGHT_PATH_FILESTAT_SET_SIZE Rights_t = 0x0000000000080000 + RIGHT_PATH_FILESTAT_SET_TIMES Rights_t = 0x0000000000100000 + RIGHT_FD_FILESTAT_GET Rights_t = 0x0000000000200000 + RIGHT_FD_FILESTAT_SET_SIZE Rights_t = 0x0000000000400000 + RIGHT_FD_FILESTAT_SET_TIMES Rights_t = 0x0000000000800000 + RIGHT_PATH_SYMLINK Rights_t = 0x0000000001000000 + RIGHT_PATH_REMOVE_DIRECTORY Rights_t = 0x0000000002000000 + RIGHT_PATH_UNLINK_FILE Rights_t = 0x0000000004000000 + RIGHT_POLL_FD_READWRITE Rights_t = 0x0000000008000000 + RIGHT_SOCK_SHUTDOWN Rights_t = 0x0000000010000000 + + FILETYPE_UNKNOWN Filetype_t = 0 + FILETYPE_BLOCK_DEVICE Filetype_t = 1 + FILETYPE_CHARACTER_DEVICE Filetype_t = 2 + FILETYPE_DIRECTORY Filetype_t = 3 + FILETYPE_REGULAR_FILE Filetype_t = 4 + FILETYPE_SOCKET_DGRAM Filetype_t = 5 + FILETYPE_SOCKET_STREAM Filetype_t = 6 + FILETYPE_SYMBOLIC_LINK Filetype_t = 7 + + WHENCE_CUR Whence_t = 0 + WHENCE_END Whence_t = 1 + WHENCE_SET Whence_t = 2 + + FILESTAT_SET_ATIM Fstflags_t = 0x0001 + FILESTAT_SET_ATIM_NOW Fstflags_t = 0x0002 + FILESTAT_SET_MTIM Fstflags_t = 0x0004 + FILESTAT_SET_MTIM_NOW Fstflags_t = 0x0008 +) + +//go:wasmimport Fd_close wasi_unstable fd_close +func Fd_close( + fd Fd_t, +) Errno + +//go:wasmimport Fd_filestat_set_size wasi_unstable fd_filestat_set_size +func Fd_filestat_set_size( + fd Fd_t, + st_size Filesize_t, +) Errno + +//go:wasmimport Fd_pread wasi_unstable fd_pread +func Fd_pread( + fd Fd_t, + iovs *Ciovec_t, + iovs_len size_t, + offset Filesize_t, + nread *size_t, +) Errno + +//go:wasmimport Fd_pwrite wasi_unstable fd_pwrite +func Fd_pwrite( + fd Fd_t, + iovs *Ciovec_t, + iovs_len size_t, + offset Filesize_t, + nwritten *size_t, +) Errno + +//go:wasmimport Fd_read wasi_unstable fd_read +func Fd_read( + fd Fd_t, + iovs *Ciovec_t, + iovs_len size_t, + nread *size_t, +) Errno + +//go:wasmimport Fd_readdir wasi_unstable fd_readdir +func Fd_readdir( + fd Fd_t, + buf *byte, + buf_len size_t, + cookie Dircookie_t, + bufused *size_t, +) Errno + +//go:wasmimport Fd_seek wasi_unstable fd_seek +func Fd_seek( + fd Fd_t, + offset Filedelta_t, + whence Whence_t, + newoffset *Filesize_t, +) Errno + +//go:wasmimport Fd_fdstat_get wasi_unstable fd_fdstat_get +func Fd_fdstat_get( + fd Fd_t, + buf *Fdstat_t, +) Errno + +//go:wasmimport Fd_filestat_get wasi_unstable fd_filestat_get +func Fd_filestat_get( + fd Fd_t, + buf *Stat_t, +) Errno + +//go:wasmimport Fd_write wasi_unstable fd_write +func Fd_write( + fd Fd_t, + iovs *Ciovec_t, + iovs_len size_t, + nwritten *size_t, +) Errno + +//go:wasmimport Path_create_directory wasi_unstable path_create_directory +func Path_create_directory( + fd Fd_t, + path *byte, + path_len size_t, +) Errno + +//go:wasmimport Path_filestat_get wasi_unstable path_filestat_get +func Path_filestat_get( + fd Fd_t, + flags Lookupflags_t, + path *byte, + path_len size_t, + buf *Stat_t, +) Errno + +//go:wasmimport Path_filestat_set_times wasi_unstable path_filestat_set_times +func Path_filestat_set_times( + fd Fd_t, + flags Lookupflags_t, + path *byte, + path_len size_t, + st_atim Timestamp_t, + st_mtim Timestamp_t, + fstflags Fstflags_t, +) Errno + +//go:wasmimport Path_link wasi_unstable path_link +func Path_link( + old_fd Fd_t, + old_flags Lookupflags_t, + old_path *byte, + old_path_len size_t, + new_fd Fd_t, + new_path *byte, + new_path_len size_t, +) Errno + +//go:wasmimport Path_readlink wasi_unstable path_readlink +func Path_readlink( + fd Fd_t, + path *byte, + path_len size_t, + buf *byte, + buf_len size_t, + bufused *size_t, +) Errno + +//go:wasmimport Path_remove_directory wasi_unstable path_remove_directory +func Path_remove_directory( + fd Fd_t, + path *byte, + path_len size_t, +) Errno + +//go:wasmimport Path_rename wasi_unstable path_rename +func Path_rename( + old_fd Fd_t, + old_path *byte, + old_path_len size_t, + new_fd Fd_t, + new_path *byte, + new_path_len size_t, +) Errno + +//go:wasmimport Path_symlink wasi_unstable path_symlink +func Path_symlink( + old_path *byte, + old_path_len size_t, + fd Fd_t, + new_path *byte, + new_path_len size_t, +) Errno + +//go:wasmimport Path_unlink_file wasi_unstable path_unlink_file +func Path_unlink_file( + fd Fd_t, + path *byte, + path_len size_t, +) Errno + +//go:wasmimport Path_open wasi_unstable path_open +func Path_open( + rootFD Fd_t, + dirflags Lookupflags_t, + path *byte, + path_len size_t, + oflags Oflags_t, + fs_rights_base Rights_t, + fs_rights_inheriting Rights_t, + fs_flags Fdflags_t, + fd *Fd_t, +) Errno + +//go:wasmimport Random_get wasi_unstable random_get +func Random_get( + buf *byte, + buf_len size_t, +) Errno + +const rootFD Fd_t = 3 + +var rootRightsDir Rights_t +var rootRightsFile Rights_t + +var wd string + +var fdPathsMu sync.Mutex +var fdPaths = make(map[int]string) + +func init() { + var stat Fdstat_t + errno := Fd_fdstat_get(rootFD, &stat) + if errno != 0 { + panic("cloud not get fdstat of root: " + errno.Error()) + } + rootRightsDir = stat.RightsBase + rootRightsFile = stat.RightsInheriting + + wd, _ = Getenv("PWD") +} + +// Provided by package runtime. +func now() (sec int64, nsec int32) + +func preparePath(path string, followTrailingSymlink bool) (*byte, size_t) { + if path == "" || path[0] != '/' { + path = wd + "/" + path + } + + parts := strings.Split(path[1:], "/") + resolvedPath := "" + for i, part := range parts { + resolvedPath += "/" + part + if i == len(parts)-1 && !followTrailingSymlink { + break + } + for { + dest, err := readlink("." + resolvedPath) + if err != nil { + break + } + if dest[0] != '/' { + i := strings.LastIndexByte(resolvedPath, '/') + dest = resolvedPath[:i] + "/" + dest + } + resolvedPath = dest + } + } + + return &[]byte("." + resolvedPath)[0], size_t(1 + len(resolvedPath)) +} + +func readlink(path string) (string, error) { + for buflen := size_t(128); ; buflen *= 2 { + buf := make([]byte, buflen) + var bufused size_t + errno := Path_readlink( + rootFD, + &[]byte(path)[0], + size_t(len(path)), + &buf[0], + buflen, + &bufused, + ) + if errno != 0 { + return "", errnoErr(errno) + } + if bufused < buflen { + return string(buf[:bufused]), nil + } + } +} + +func Open(path string, openmode int, perm uint32) (int, error) { + if path == "" { + return 0, EINVAL + } + if path[0] != '/' { + path = wd + "/" + path + } + + path_ptr, path_len := preparePath(path, true) + + var oflags Oflags_t + if openmode&O_CREATE != 0 { + oflags |= OFLAG_CREATE + } + if openmode&O_TRUNC != 0 { + oflags |= OFLAG_TRUNC + } + if openmode&O_EXCL != 0 { + oflags |= OFLAG_EXCL + } + + var rights = rootRightsFile + switch { + case openmode&O_WRONLY != 0: + rights &^= RIGHT_FD_READ | RIGHT_FD_READDIR + case openmode&O_RDWR != 0: + // no rights to remove + default: + rights &^= RIGHT_FD_DATASYNC | RIGHT_FD_WRITE | RIGHT_FD_ALLOCATE | RIGHT_PATH_FILESTAT_SET_SIZE + } + + var fdflags Fdflags_t + if openmode&O_APPEND != 0 { + fdflags |= FDFLAG_APPEND + } + if openmode&O_SYNC != 0 { + fdflags |= FDFLAG_SYNC + } + + var fd Fd_t + errno := Path_open( + rootFD, + 0, + path_ptr, + path_len, + oflags, + rights, + rootRightsFile, + fdflags, + &fd, + ) + + fdPathsMu.Lock() + fdPaths[int(fd)] = path + fdPathsMu.Unlock() + + return int(fd), errnoErr(errno) +} + +func Close(fd int) error { + fdPathsMu.Lock() + delete(fdPaths, fd) + fdPathsMu.Unlock() + + errno := Fd_close(Fd_t(fd)) + return errnoErr(errno) +} + +func CloseOnExec(fd int) { + // nothing to do - no exec +} + +func Mkdir(path string, perm uint32) error { + path_ptr, path_len := preparePath(path, false) + errno := Path_create_directory(rootFD, path_ptr, path_len) + return errnoErr(errno) +} + +func ReadDirent(fd int, buf []byte) (int, error) { + return 0, ENOSYS +} + +func ReadDir(fd int, buf []byte, cookie Dircookie_t) (int, error) { + var bufused size_t + errno := Fd_readdir(Fd_t(fd), &buf[0], size_t(len(buf)), cookie, &bufused) + return int(bufused), errnoErr(errno) +} + +func Stat(path string, st *Stat_t) error { + path_ptr, path_len := preparePath(path, true) + errno := Path_filestat_get(rootFD, 0, path_ptr, path_len, st) + return errnoErr(errno) +} + +func Lstat(path string, st *Stat_t) error { + path_ptr, path_len := preparePath(path, false) + errno := Path_filestat_get(rootFD, 0, path_ptr, path_len, st) + return errnoErr(errno) +} + +func Fstat(fd int, st *Stat_t) error { + errno := Fd_filestat_get(Fd_t(fd), st) + return errnoErr(errno) +} + +func Unlink(path string) error { + path_ptr, path_len := preparePath(path, false) + errno := Path_unlink_file(rootFD, path_ptr, path_len) + return errnoErr(errno) +} + +func Rmdir(path string) error { + path_ptr, path_len := preparePath(path, false) + errno := Path_remove_directory(rootFD, path_ptr, path_len) + return errnoErr(errno) +} + +func Chmod(path string, mode uint32) error { + return ENOSYS +} + +func Fchmod(fd int, mode uint32) error { + return ENOSYS +} + +func Chown(path string, uid, gid int) error { + return ENOSYS +} + +func Fchown(fd int, uid, gid int) error { + return ENOSYS +} + +func Lchown(path string, uid, gid int) error { + return ENOSYS +} + +func UtimesNano(path string, ts []Timespec) error { + path_ptr, path_len := preparePath(path, false) + errno := Path_filestat_set_times( + rootFD, + 0, + path_ptr, + path_len, + Timestamp_t(TimespecToNsec(ts[0])), + Timestamp_t(TimespecToNsec(ts[1])), + FILESTAT_SET_ATIM|FILESTAT_SET_MTIM, + ) + return errnoErr(errno) +} + +func Rename(from, to string) error { + old_path, old_path_len := preparePath(from, false) + new_path, new_path_len := preparePath(to, false) + errno := Path_rename( + rootFD, + old_path, + old_path_len, + rootFD, + new_path, + new_path_len, + ) + return errnoErr(errno) +} + +func Truncate(path string, length int64) error { + fd, openErr := Open(path, O_WRONLY, 0) + if openErr != nil { + return openErr + } + truncateErr := Ftruncate(fd, length) + closeErr := Close(fd) + if truncateErr != nil { + return truncateErr + } + return closeErr +} + +func Ftruncate(fd int, length int64) error { + errno := Fd_filestat_set_size(Fd_t(fd), Filesize_t(length)) + return errnoErr(errno) +} + +const ImplementsGetwd = true + +func Getwd() (string, error) { + return wd, nil +} + +func Chdir(path string) (err error) { + if path[0] != '/' { + path = wd + "/" + path + } + var st Stat_t + if err := Stat(path, &st); err != nil { + return err + } + wd = path + return nil +} + +func Fchdir(fd int) error { + fdPathsMu.Lock() + wd = fdPaths[fd] + fdPathsMu.Unlock() + return nil +} + +func Readlink(path string, buf []byte) (n int, err error) { + path_ptr, path_len := preparePath(path, false) + var bufused size_t + errno := Path_readlink( + rootFD, + path_ptr, + path_len, + &buf[0], + size_t(len(buf)), + &bufused, + ) + return int(bufused), errnoErr(errno) +} + +func Link(path, link string) error { + old_path, old_path_len := preparePath(path, false) + new_path, new_path_len := preparePath(link, false) + errno := Path_link( + rootFD, + 0, + old_path, + old_path_len, + rootFD, + new_path, + new_path_len, + ) + return errnoErr(errno) +} + +func Symlink(path, link string) error { + new_path, new_path_len := preparePath(link, false) + errno := Path_symlink( + &[]byte(path)[0], + size_t(len(path)), + rootFD, + new_path, + new_path_len, + ) + return errnoErr(errno) +} + +func Fsync(fd int) error { + return ENOSYS +} + +func makeIOVec(b []byte) *Ciovec_t { + return &Ciovec_t{ + buf: uintptr_t(uintptr(unsafe.Pointer(&b[0]))), + buf_len: size_t(len(b)), + } +} + +func Read(fd int, b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + var nread size_t + errno := Fd_read(Fd_t(fd), makeIOVec(b), 1, &nread) + return int(nread), errnoErr(errno) +} + +func Write(fd int, b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + var nwritten size_t + errno := Fd_write(Fd_t(fd), makeIOVec(b), 1, &nwritten) + return int(nwritten), errnoErr(errno) +} + +func Pread(fd int, b []byte, offset int64) (int, error) { + if len(b) == 0 { + return 0, nil + } + var nread size_t + errno := Fd_pread(Fd_t(fd), makeIOVec(b), 1, Filesize_t(offset), &nread) + return int(nread), errnoErr(errno) +} + +func Pwrite(fd int, b []byte, offset int64) (int, error) { + if len(b) == 0 { + return 0, nil + } + var nwritten size_t + errno := Fd_pwrite(Fd_t(fd), makeIOVec(b), 1, Filesize_t(offset), &nwritten) + return int(nwritten), errnoErr(errno) +} + +func Seek(fd int, offset int64, whence int) (int64, error) { + var wasiWhence Whence_t + switch whence { + case io.SeekStart: + wasiWhence = WHENCE_SET + case io.SeekCurrent: + wasiWhence = WHENCE_CUR + case io.SeekEnd: + wasiWhence = WHENCE_END + default: + return 0, errnoErr(EINVAL) + } + var newoffset Filesize_t + errno := Fd_seek(Fd_t(fd), Filedelta_t(offset), wasiWhence, &newoffset) + return int64(newoffset), errnoErr(errno) +} + +func Dup(fd int) (int, error) { + return 0, ENOSYS +} + +func Dup2(fd, newfd int) error { + return ENOSYS +} + +func Pipe(fd []int) error { + return ENOSYS +} + +func RandomGet(b []byte) error { + if len(b) == 0 { + return nil + } + errno := Random_get(&b[0], size_t(len(b))) + return errnoErr(errno) +} diff --git a/src/syscall/net_wasi.go b/src/syscall/net_wasi.go new file mode 100644 index 0000000000000..a004972f8d2f8 --- /dev/null +++ b/src/syscall/net_wasi.go @@ -0,0 +1,126 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// js/wasm uses fake networking directly implemented in the net package. +// This file only exists to make the compiler happy. + +package syscall + +const ( + AF_UNSPEC = iota + AF_UNIX + AF_INET + AF_INET6 +) + +const ( + SOCK_STREAM = 1 + iota + SOCK_DGRAM + SOCK_RAW + SOCK_SEQPACKET +) + +const ( + IPPROTO_IP = 0 + IPPROTO_IPV4 = 4 + IPPROTO_IPV6 = 0x29 + IPPROTO_TCP = 6 + IPPROTO_UDP = 0x11 +) + +const ( + _ = iota + IPV6_V6ONLY + SOMAXCONN + SO_ERROR +) + +// Misc constants expected by package net but not supported. +const ( + _ = iota + F_DUPFD_CLOEXEC + SYS_FCNTL = 500 // unsupported; same value as net_nacl.go +) + +type Sockaddr interface { +} + +type SockaddrInet4 struct { + Port int + Addr [4]byte +} + +type SockaddrInet6 struct { + Port int + ZoneId uint32 + Addr [16]byte +} + +type SockaddrUnix struct { + Name string +} + +func Socket(proto, sotype, unused int) (fd int, err error) { + return 0, ENOSYS +} + +func Bind(fd int, sa Sockaddr) error { + return ENOSYS +} + +func StopIO(fd int) error { + return ENOSYS +} + +func Listen(fd int, backlog int) error { + return ENOSYS +} + +func Accept(fd int) (newfd int, sa Sockaddr, err error) { + return 0, nil, ENOSYS +} + +func Connect(fd int, sa Sockaddr) error { + return ENOSYS +} + +func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { + return 0, nil, ENOSYS +} + +func Sendto(fd int, p []byte, flags int, to Sockaddr) error { + return ENOSYS +} + +func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) { + return 0, 0, 0, nil, ENOSYS +} + +func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { + return 0, ENOSYS +} + +func GetsockoptInt(fd, level, opt int) (value int, err error) { + return 0, ENOSYS +} + +func SetsockoptInt(fd, level, opt int, value int) error { + return nil +} + +func SetReadDeadline(fd int, t int64) error { + return ENOSYS +} + +func SetWriteDeadline(fd int, t int64) error { + return ENOSYS +} + +func Shutdown(fd int, how int) error { + return ENOSYS +} + +func SetNonblock(fd int, nonblocking bool) error { + return nil +} diff --git a/src/syscall/syscall_wasi.go b/src/syscall/syscall_wasi.go new file mode 100644 index 0000000000000..a3443364b6be9 --- /dev/null +++ b/src/syscall/syscall_wasi.go @@ -0,0 +1,309 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +import ( + "internal/oserror" + "sync" +) + +type Dirent struct { + Next Dircookie_t + Ino Inode_t + Namlen uint32 + Type Filetype_t + Name *byte +} + +func direntIno(buf []byte) (uint64, bool) { + return 1, true +} + +func direntReclen(buf []byte) (uint64, bool) { + namelen, ok := readInt(buf, 16, 4) + return 24 + namelen, ok + // return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + return readInt(buf, 16, 4) +} + +const PathMax = 256 + +// An Errno is an unsigned number describing an error condition. +// It implements the error interface. The zero Errno is by convention +// a non-error, so code to convert from Errno to error should use: +// err = nil +// if errno != 0 { +// err = errno +// } +type Errno uint32 + +func (e Errno) Error() string { + if 0 <= int(e) && int(e) < len(errorstr) { + s := errorstr[e] + if s != "" { + return s + } + } + return "errno " + itoa(int(e)) +} + +func (e Errno) Is(target error) bool { + switch target { + case oserror.ErrPermission: + return e == EACCES || e == EPERM + case oserror.ErrExist: + return e == EEXIST || e == ENOTEMPTY + case oserror.ErrNotExist: + return e == ENOENT + } + return false +} + +func (e Errno) Temporary() bool { + return e == EINTR || e == EMFILE || e.Timeout() +} + +func (e Errno) Timeout() bool { + return e == EAGAIN || e == ETIMEDOUT +} + +// A Signal is a number describing a process signal. +// It implements the os.Signal interface. +type Signal int + +const ( + _ Signal = iota + SIGCHLD + SIGINT + SIGKILL + SIGTRAP + SIGQUIT + SIGTERM +) + +func (s Signal) Signal() {} + +func (s Signal) String() string { + if 0 <= s && int(s) < len(signals) { + str := signals[s] + if str != "" { + return str + } + } + return "signal " + itoa(int(s)) +} + +var signals = [...]string{} + +// File system + +const ( + Stdin = 0 + Stdout = 1 + Stderr = 2 +) + +const ( + O_RDONLY = 0 + O_WRONLY = 1 + O_RDWR = 2 + + O_CREAT = 0100 + O_CREATE = O_CREAT + O_TRUNC = 01000 + O_APPEND = 02000 + O_EXCL = 0200 + O_SYNC = 010000 + + O_CLOEXEC = 0 +) + +const ( + F_DUPFD = 0 + F_GETFD = 1 + F_SETFD = 2 + F_GETFL = 3 + F_SETFL = 4 + F_GETOWN = 5 + F_SETOWN = 6 + F_GETLK = 7 + F_SETLK = 8 + F_SETLKW = 9 + F_RGETLK = 10 + F_RSETLK = 11 + F_CNVT = 12 + F_RSETLKW = 13 + + F_RDLCK = 1 + F_WRLCK = 2 + F_UNLCK = 3 + F_UNLKSYS = 4 +) + +const ( + S_IFMT = 0000370000 + S_IFSHM_SYSV = 0000300000 + S_IFSEMA = 0000270000 + S_IFCOND = 0000260000 + S_IFMUTEX = 0000250000 + S_IFSHM = 0000240000 + S_IFBOUNDSOCK = 0000230000 + S_IFSOCKADDR = 0000220000 + S_IFDSOCK = 0000210000 + + S_IFSOCK = 0000140000 + S_IFLNK = 0000120000 + S_IFREG = 0000100000 + S_IFBLK = 0000060000 + S_IFDIR = 0000040000 + S_IFCHR = 0000020000 + S_IFIFO = 0000010000 + + S_UNSUP = 0000370000 + + S_ISUID = 0004000 + S_ISGID = 0002000 + S_ISVTX = 0001000 + + S_IREAD = 0400 + S_IWRITE = 0200 + S_IEXEC = 0100 + + S_IRWXU = 0700 + S_IRUSR = 0400 + S_IWUSR = 0200 + S_IXUSR = 0100 + + S_IRWXG = 070 + S_IRGRP = 040 + S_IWGRP = 020 + S_IXGRP = 010 + + S_IRWXO = 07 + S_IROTH = 04 + S_IWOTH = 02 + S_IXOTH = 01 +) + +// Processes +// Not supported - just enough for package os. + +var ForkLock sync.RWMutex + +type WaitStatus uint32 + +func (w WaitStatus) Exited() bool { return false } +func (w WaitStatus) ExitStatus() int { return 0 } +func (w WaitStatus) Signaled() bool { return false } +func (w WaitStatus) Signal() Signal { return 0 } +func (w WaitStatus) CoreDump() bool { return false } +func (w WaitStatus) Stopped() bool { return false } +func (w WaitStatus) Continued() bool { return false } +func (w WaitStatus) StopSignal() Signal { return 0 } +func (w WaitStatus) TrapCause() int { return 0 } + +// XXX made up +type Rusage struct { + Utime Timeval + Stime Timeval +} + +// XXX made up +type ProcAttr struct { + Dir string + Env []string + Files []uintptr + Sys *SysProcAttr +} + +type SysProcAttr struct { +} + +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + return 0, 0, ENOSYS +} + +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + return 0, 0, ENOSYS +} + +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + return 0, 0, ENOSYS +} + +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + return 0, 0, ENOSYS +} + +func Sysctl(key string) (string, error) { + if key == "kern.hostname" { + return "js", nil + } + return "", ENOSYS +} + +func Getuid() int { + return 1 +} + +func Getgid() int { + return 1 +} + +func Geteuid() int { + return 1 +} + +func Getegid() int { + return 1 +} + +func Getgroups() ([]int, error) { + return []int{1}, nil +} + +func Getpid() int { + return 3 +} + +func Getppid() int { + return 2 +} + +func Gettimeofday(tv *Timeval) error { return ENOSYS } + +func Kill(pid int, signum Signal) error { return ENOSYS } +func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + return 0, ENOSYS +} +func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) { + return 0, 0, ENOSYS +} +func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + return 0, ENOSYS +} + +type Iovec struct{} // dummy + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: sec, Usec: usec} +} diff --git a/src/syscall/tables_wasi.go b/src/syscall/tables_wasi.go new file mode 100644 index 0000000000000..12e73d88b629e --- /dev/null +++ b/src/syscall/tables_wasi.go @@ -0,0 +1,278 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +import "runtime" + +// TODO: generate with runtime/mknacl.sh, allow override with IRT. +const ( + sys_null = 1 + sys_nameservice = 2 + sys_dup = 8 + sys_dup2 = 9 + sys_open = 10 + sys_close = 11 + sys_read = 12 + sys_write = 13 + sys_lseek = 14 + sys_stat = 16 + sys_fstat = 17 + sys_chmod = 18 + sys_isatty = 19 + sys_brk = 20 + sys_mmap = 21 + sys_munmap = 22 + sys_getdents = 23 + sys_mprotect = 24 + sys_list_mappings = 25 + sys_exit = 30 + sys_getpid = 31 + sys_sched_yield = 32 + sys_sysconf = 33 + sys_gettimeofday = 40 + sys_clock = 41 + sys_nanosleep = 42 + sys_clock_getres = 43 + sys_clock_gettime = 44 + sys_mkdir = 45 + sys_rmdir = 46 + sys_chdir = 47 + sys_getcwd = 48 + sys_unlink = 49 + sys_imc_makeboundsock = 60 + sys_imc_accept = 61 + sys_imc_connect = 62 + sys_imc_sendmsg = 63 + sys_imc_recvmsg = 64 + sys_imc_mem_obj_create = 65 + sys_imc_socketpair = 66 + sys_mutex_create = 70 + sys_mutex_lock = 71 + sys_mutex_trylock = 72 + sys_mutex_unlock = 73 + sys_cond_create = 74 + sys_cond_wait = 75 + sys_cond_signal = 76 + sys_cond_broadcast = 77 + sys_cond_timed_wait_abs = 79 + sys_thread_create = 80 + sys_thread_exit = 81 + sys_tls_init = 82 + sys_thread_nice = 83 + sys_tls_get = 84 + sys_second_tls_set = 85 + sys_second_tls_get = 86 + sys_exception_handler = 87 + sys_exception_stack = 88 + sys_exception_clear_flag = 89 + sys_sem_create = 100 + sys_sem_wait = 101 + sys_sem_post = 102 + sys_sem_get_value = 103 + sys_dyncode_create = 104 + sys_dyncode_modify = 105 + sys_dyncode_delete = 106 + sys_test_infoleak = 109 + sys_test_crash = 110 + sys_test_syscall_1 = 111 + sys_test_syscall_2 = 112 + sys_futex_wait_abs = 120 + sys_futex_wake = 121 + sys_pread = 130 + sys_pwrite = 131 + sys_truncate = 140 + sys_lstat = 141 + sys_link = 142 + sys_rename = 143 + sys_symlink = 144 + sys_access = 145 + sys_readlink = 146 + sys_utimes = 147 + sys_get_random_bytes = 150 +) + +// TODO: Auto-generate some day. (Hard-coded in binaries so not likely to change.) +const ( + E2BIG Errno = 1 + EACCES Errno = 2 + EADDRINUSE Errno = 3 + EADDRNOTAVAIL Errno = 4 + EAFNOSUPPORT Errno = 5 + EAGAIN Errno = 6 + EALREADY Errno = 7 + EBADF Errno = 8 + EBADMSG Errno = 9 + EBUSY Errno = 10 + ECANCELED Errno = 11 + ECHILD Errno = 12 + ECONNABORTED Errno = 13 + ECONNREFUSED Errno = 14 + ECONNRESET Errno = 15 + EDEADLK Errno = 16 + EDESTADDRREQ Errno = 17 + EDOM Errno = 18 + EDQUOT Errno = 19 + EEXIST Errno = 20 + EFAULT Errno = 21 + EFBIG Errno = 22 + EHOSTUNREACH Errno = 23 + EIDRM Errno = 24 + EILSEQ Errno = 25 + EINPROGRESS Errno = 26 + EINTR Errno = 27 + EINVAL Errno = 28 + EIO Errno = 29 + EISCONN Errno = 30 + EISDIR Errno = 31 + ELOOP Errno = 32 + EMFILE Errno = 33 + EMLINK Errno = 34 + EMSGSIZE Errno = 35 + EMULTIHOP Errno = 36 + ENAMETOOLONG Errno = 37 + ENETDOWN Errno = 38 + ENETRESET Errno = 39 + ENETUNREACH Errno = 40 + ENFILE Errno = 41 + ENOBUFS Errno = 42 + ENODEV Errno = 43 + ENOENT Errno = 44 + ENOEXEC Errno = 45 + ENOLCK Errno = 46 + ENOLINK Errno = 47 + ENOMEM Errno = 48 + ENOMSG Errno = 49 + ENOPROTOOPT Errno = 50 + ENOSPC Errno = 51 + ENOSYS Errno = 52 + ENOTCONN Errno = 53 + ENOTDIR Errno = 54 + ENOTEMPTY Errno = 55 + ENOTRECOVERABLE Errno = 56 + ENOTSOCK Errno = 57 + ENOTSUP Errno = 58 + ENOTTY Errno = 59 + ENXIO Errno = 60 + EOVERFLOW Errno = 61 + EOWNERDEAD Errno = 62 + EPERM Errno = 63 + EPIPE Errno = 64 + EPROTO Errno = 65 + EPROTONOSUPPORT Errno = 66 + EPROTOTYPE Errno = 67 + ERANGE Errno = 68 + EROFS Errno = 69 + ESPIPE Errno = 70 + ESRCH Errno = 71 + ESTALE Errno = 72 + ETIMEDOUT Errno = 73 + ETXTBSY Errno = 74 + EXDEV Errno = 75 + ENOTCAPABLE Errno = 76 +) + +// TODO: Auto-generate some day. (Hard-coded in binaries so not likely to change.) +var errorstr = [...]string{ + E2BIG: "Argument list too long", + EACCES: "Permission denied", + EADDRINUSE: "Address already in use", + EADDRNOTAVAIL: "Address not available", + EAFNOSUPPORT: "Address family not supported by protocol family", + EAGAIN: "Try again", + EALREADY: "Socket already connected", + EBADF: "Bad file number", + EBADMSG: "Trying to read unreadable message", + EBUSY: "Device or resource busy", + ECANCELED: "Operation canceled.", + ECHILD: "No child processes", + ECONNABORTED: "Connection aborted", + ECONNREFUSED: "Connection refused", + ECONNRESET: "Connection reset by peer", + EDEADLK: "Deadlock condition", + EDESTADDRREQ: "Destination address required", + EDOM: "Math arg out of domain of func", + EDQUOT: "Quota exceeded", + EEXIST: "File exists", + EFAULT: "Bad address", + EFBIG: "File too large", + EHOSTUNREACH: "Host is unreachable", + EIDRM: "Identifier removed", + EILSEQ: "EILSEQ", + EINPROGRESS: "Connection already in progress", + EINTR: "Interrupted system call", + EINVAL: "Invalid argument", + EIO: "I/O error", + EISCONN: "Socket is already connected", + EISDIR: "Is a directory", + ELOOP: "Too many symbolic links", + EMFILE: "Too many open files", + EMLINK: "Too many links", + EMSGSIZE: "Message too long", + EMULTIHOP: "Multihop attempted", + ENAMETOOLONG: "File name too long", + ENETDOWN: "Network interface is not configured", + ENETRESET: "Network dropped connection on reset", + ENETUNREACH: "Network is unreachable", + ENFILE: "File table overflow", + ENOBUFS: "No buffer space available", + ENODEV: "No such device", + ENOENT: "No such file or directory", + ENOEXEC: "Exec format error", + ENOLCK: "No record locks available", + ENOLINK: "The link has been severed", + ENOMEM: "Out of memory", + ENOMSG: "No message of desired type", + ENOPROTOOPT: "Protocol not available", + ENOSPC: "No space left on device", + ENOSYS: "Not implemented on " + runtime.GOOS, + ENOTCONN: "Socket is not connected", + ENOTDIR: "Not a directory", + ENOTEMPTY: "Directory not empty", + ENOTRECOVERABLE: "State not recoverable", + ENOTSOCK: "Socket operation on non-socket", + ENOTSUP: "Not supported", + ENOTTY: "Not a typewriter", + ENXIO: "No such device or address", + EOVERFLOW: "Value too large for defined data type", + EOWNERDEAD: "Owner died", + EPERM: "Operation not permitted", + EPIPE: "Broken pipe", + EPROTO: "Protocol error", + EPROTONOSUPPORT: "Unknown protocol", + EPROTOTYPE: "Protocol wrong type for socket", + ERANGE: "Math result not representable", + EROFS: "Read-only file system", + ESPIPE: "Illegal seek", + ESRCH: "No such process", + ESTALE: "Stale file handle", + ETIMEDOUT: "Connection timed out", + ETXTBSY: "Text file busy", + EXDEV: "Cross-device link", + ENOTCAPABLE: "Capabilities insufficient", +} + +// Do the interface allocations only once for common +// Errno values. +var ( + errEAGAIN error = EAGAIN + errEINVAL error = EINVAL + errENOENT error = ENOENT +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e Errno) error { + switch e { + case 0: + return nil + case EAGAIN: + return errEAGAIN + case EINVAL: + return errEINVAL + case ENOENT: + return errENOENT + } + return e +} diff --git a/src/syscall/timestruct.go b/src/syscall/timestruct.go index 682c68cf9beee..0f086f2bd7b7c 100644 --- a/src/syscall/timestruct.go +++ b/src/syscall/timestruct.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package syscall diff --git a/src/time/sys_unix.go b/src/time/sys_unix.go index 97b1140bbcff9..6c7adbdea8349 100644 --- a/src/time/sys_unix.go +++ b/src/time/sys_unix.go @@ -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 aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris wasi package time diff --git a/src/time/zoneinfo_wasi.go b/src/time/zoneinfo_wasi.go new file mode 100644 index 0000000000000..12eb03288980d --- /dev/null +++ b/src/time/zoneinfo_wasi.go @@ -0,0 +1,41 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package time + +import ( + "runtime" +) + +var zoneSources = []string{ + "/usr/share/zoneinfo/", + "/usr/share/lib/zoneinfo/", + "/usr/lib/locale/TZ/", + runtime.GOROOT() + "/lib/time/zoneinfo.zip", +} + +func initLocal() { + localLoc.name = "Local" +} + +// itoa is like strconv.Itoa but only works for values of i in range [0,99]. +// It panics if i is out of range. +func itoa(i int) string { + if i < 10 { + return digits[i : i+1] + } + return smallsString[i*2 : i*2+2] +} + +const smallsString = "00010203040506070809" + + "10111213141516171819" + + "20212223242526272829" + + "30313233343536373839" + + "40414243444546474849" + + "50515253545556575859" + + "60616263646566676869" + + "70717273747576777879" + + "80818283848586878889" + + "90919293949596979899" +const digits = "0123456789"