// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris
+//go:build aix || dragonfly || freebsd || (js && wasm) || wasip1 || linux || netbsd || openbsd || solaris
package os
--- /dev/null
+// Copyright 2023 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.
+
+//go:build wasip1
+
+package os
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-dirent-record
+const sizeOfDirent = 24
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Ino), unsafe.Sizeof(syscall.Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ namelen, ok := direntNamlen(buf)
+ return sizeOfDirent + namelen, ok
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Namlen), unsafe.Sizeof(syscall.Dirent{}.Namlen))
+}
+
+func direntType(buf []byte) FileMode {
+ off := unsafe.Offsetof(syscall.Dirent{}.Type)
+ if off >= uintptr(len(buf)) {
+ return ^FileMode(0) // unknown
+ }
+ switch syscall.Filetype(buf[off]) {
+ case syscall.FILETYPE_BLOCK_DEVICE:
+ return ModeDevice
+ case syscall.FILETYPE_CHARACTER_DEVICE:
+ return ModeDevice | ModeCharDevice
+ case syscall.FILETYPE_DIRECTORY:
+ return ModeDir
+ case syscall.FILETYPE_REGULAR_FILE:
+ return 0
+ case syscall.FILETYPE_SOCKET_DGRAM:
+ return ModeSocket
+ case syscall.FILETYPE_SOCKET_STREAM:
+ return ModeSocket
+ case syscall.FILETYPE_SYMBOLIC_LINK:
+ return ModeSymlink
+ }
+ return ^FileMode(0) // unknown
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm) || windows
+//go:build unix || (js && wasm) || wasip1 || windows
package os
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os_test
+++ /dev/null
-// Copyright 2021 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.
-
-//go:build js
-
-package fdtest
-
-import (
- "syscall"
-)
-
-// Exists returns true if fd is a valid file descriptor.
-func Exists(fd uintptr) bool {
- var s syscall.Stat_t
- err := syscall.Fstat(int(fd), &s)
- return err != syscall.EBADF
-}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix
+//go:build unix || wasm
// Package fdtest provides test helpers for working with file descriptors across exec.
package fdtest
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build js && wasm
+//go:build wasm
package exec
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm) || windows
+//go:build unix || (js && wasm) || wasip1 || windows
package os
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build linux || netbsd || (js && wasm)
+//go:build linux || netbsd
package os
--- /dev/null
+// Copyright 2023 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.
+
+//go:build wasm
+
+package os
+
+import (
+ "errors"
+ "runtime"
+)
+
+func executable() (string, error) {
+ return "", errors.New("Executable not implemented for " + runtime.GOOS)
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os
--- /dev/null
+// Copyright 2023 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.
+
+//go:build unix || (js && wasm)
+
+package os
+
+import (
+ "internal/poll"
+ "syscall"
+)
+
+func open(path string, flag int, perm uint32) (int, poll.SysFile, error) {
+ fd, err := syscall.Open(path, flag, perm)
+ return fd, poll.SysFile{}, err
+}
--- /dev/null
+// Copyright 2023 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.
+
+//go:build wasip1
+
+package os
+
+import (
+ "internal/poll"
+ "syscall"
+)
+
+func open(filePath string, flag int, perm uint32) (int, poll.SysFile, error) {
+ if filePath == "" {
+ return -1, poll.SysFile{}, syscall.EINVAL
+ }
+ absPath := filePath
+ // os.(*File).Chdir is emulated by setting the working directory to the
+ // absolute path that this file was opened at, which is why we have to
+ // resolve and capture it here.
+ if filePath[0] != '/' {
+ wd, err := syscall.Getwd()
+ if err != nil {
+ return -1, poll.SysFile{}, err
+ }
+ absPath = joinPath(wd, filePath)
+ }
+ fd, err := syscall.Open(absPath, flag, perm)
+ return fd, poll.SysFile{Path: absPath}, err
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm) || windows
+//go:build unix || (js && wasm) || wasip1 || windows
package os
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os
}
var r int
+ var s poll.SysFile
for {
var e error
- r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
+ r, s, e = open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
if e == nil {
break
}
syscall.CloseOnExec(r)
}
- return newFile(uintptr(r), name, kindOpenFile), nil
+ f := newFile(uintptr(r), name, kindOpenFile)
+ f.pfd.SysFile = s
+ return f, nil
}
func (file *file) close() error {
}
}
// buffer too small
- if runtime.GOOS == "aix" && e == syscall.ERANGE {
+ if (runtime.GOOS == "aix" || runtime.GOOS == "wasip1") && e == syscall.ERANGE {
continue
}
if e != nil {
"local",
},
}
+ case "wasip1":
+ // wasmtime has issues resolving symbolic links that are often present
+ // in directories like /etc/group below (e.g. private/etc/group on OSX).
+ // For this reason we use files in the Go source tree instead.
+ return &sysDir{
+ runtime.GOROOT(),
+ []string{
+ "go.env",
+ "LICENSE",
+ "CONTRIBUTING.md",
+ },
+ }
}
return &sysDir{
"/etc",
}
func TestChmod(t *testing.T) {
+ // Chmod is not supported on wasip1.
+ if runtime.GOOS == "wasip1" {
+ t.Skip("Chmod is not supported on " + runtime.GOOS)
+ }
t.Parallel()
f := newFile("TestChmod", t)
func TestSeekError(t *testing.T) {
switch runtime.GOOS {
- case "js", "plan9":
+ case "js", "plan9", "wasip1":
t.Skipf("skipping test on %v", runtime.GOOS)
}
t.Parallel()
}
func TestStatDirModeExec(t *testing.T) {
+ if runtime.GOOS == "wasip1" {
+ t.Skip("Chmod is not supported on " + runtime.GOOS)
+ }
t.Parallel()
const mode = 0111
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 != "wasip1" { // Chmod is not supported on wasip1
+ 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 {
t.Skip("skipping on Plan 9; does not support runtime poller")
case "js":
t.Skip("skipping on js; no support for os.Pipe")
+ case "wasip1":
+ t.Skip("skipping on wasip1; no support for os.Pipe")
}
threads := 100
// Test that it's OK to have parallel I/O and Close on a pipe.
func TestPipeIOCloseRace(t *testing.T) {
// Skip on wasm, which doesn't have pipes.
- if runtime.GOOS == "js" {
- t.Skip("skipping on js: no pipes")
+ if runtime.GOOS == "js" || runtime.GOOS == "wasip1" {
+ t.Skipf("skipping on %s: no pipes", runtime.GOOS)
}
t.Parallel()
// Test that it's OK to call Close concurrently on a pipe.
func TestPipeCloseRace(t *testing.T) {
// Skip on wasm, which doesn't have pipes.
- if runtime.GOOS == "js" {
- t.Skip("skipping on js: no pipes")
+ if runtime.GOOS == "js" || runtime.GOOS == "wasip1" {
+ t.Skipf("skipping on %s: no pipes", runtime.GOOS)
}
t.Parallel()
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os_test
import (
+ "internal/testenv"
"io"
. "os"
"path/filepath"
}
func TestChown(t *testing.T) {
+ if runtime.GOOS == "wasip1" {
+ t.Skip("file ownership not supported on " + runtime.GOOS)
+ }
t.Parallel()
// Use TempDir() to make sure we're on a local file system,
}
func TestFileChown(t *testing.T) {
+ if runtime.GOOS == "wasip1" {
+ t.Skip("file ownership not supported on " + runtime.GOOS)
+ }
t.Parallel()
// Use TempDir() to make sure we're on a local file system,
}
func TestLchown(t *testing.T) {
+ testenv.MustHaveSymlink(t)
t.Parallel()
// Use TempDir() to make sure we're on a local file system,
// Issue 23120: respect umask when doing Mkdir with the sticky bit
func TestMkdirStickyUmask(t *testing.T) {
+ if runtime.GOOS == "wasip1" {
+ t.Skip("file permissions not supported on " + runtime.GOOS)
+ }
t.Parallel()
const umask = 0077
// See also issues: 22939, 24331
func newFileTest(t *testing.T, blocking bool) {
- if runtime.GOOS == "js" {
+ if runtime.GOOS == "js" || runtime.GOOS == "wasip1" {
t.Skipf("syscall.Pipe is not available on %s.", runtime.GOOS)
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os
// Test broken pipes on Unix systems.
//
-//go:build !plan9 && !js
+//go:build !plan9 && !js && !wasip1
package os_test
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || darwin || (js && wasm)
+//go:build aix || darwin
package os
--- /dev/null
+// Copyright 2023 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.
+
+//go:build wasm
+
+package os
+
+import "syscall"
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
+ // Neither GOOS=js nor GOOS=wasip1 have pipes.
+ return nil, nil, NewSyscallError("pipe", syscall.ENOSYS)
+}
// Test use of raw connections.
//
-//go:build !plan9 && !js
+//go:build !plan9 && !js && !wasip1
package os_test
"bytes"
. "os"
"path/filepath"
+ "runtime"
"testing"
)
if Getuid() == 0 {
t.Skipf("Root can write to read-only files anyway, so skip the read-only test.")
}
+ if runtime.GOOS == "wasip1" {
+ t.Skip("no support for file permissions on " + runtime.GOOS)
+ }
t.Parallel()
// We don't want to use CreateTemp directly, since that opens a file for us as 0600.
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 or wasip1 and test fails as root.
+ if runtime.GOOS != "windows" && runtime.GOOS != "wasip1" && 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)
// Issue #29983.
func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
switch runtime.GOOS {
- case "js", "windows":
+ case "js", "wasip1", "windows":
t.Skipf("skipping test on %s", runtime.GOOS)
}
return
}
if err == nil {
- if runtime.GOOS == "windows" {
+ if runtime.GOOS == "windows" || runtime.GOOS == "wasip1" {
// Marking a directory as read-only in Windows does not prevent the RemoveAll
// from creating or removing files within it.
+ //
+ // For wasip1, there is no support for file permissions so we cannot prevent
+ // RemoveAll from removing the files.
return
}
t.Fatal("RemoveAll(<read-only directory>) = nil; want error")
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm) || windows
+//go:build unix || (js && wasm) || wasip1 || windows
package signal
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || (js && wasm)
+//go:build unix || (js && wasm) || wasip1
package os
--- /dev/null
+// Copyright 2023 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.
+
+//go:build wasip1
+
+package os
+
+import (
+ "syscall"
+ "time"
+)
+
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.mode = FileMode(fs.sys.Mode)
+ 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))
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris
+//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris || wasip1
package os
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !aix && !darwin && !dragonfly && !freebsd && (!js || !wasm) && !netbsd && !openbsd && !solaris
+//go:build !aix && !darwin && !dragonfly && !freebsd && !js && !netbsd && !openbsd && !solaris && !wasip1
package os
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd
+//go:build darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || wasip1
package os
--- /dev/null
+// Copyright 2023 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.
+
+//go:build wasip1
+
+package os
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+const supportsCloseOnExec = false
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !js && !plan9 && !windows
+//go:build !js && !plan9 && !wasip1 && !windows
package os_test
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build android || (js && !wasm)
+//go:build android
package user
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build ((darwin || dragonfly || freebsd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && ((!cgo && !darwin) || osusergo)) || aix || illumos
+//go:build ((darwin || dragonfly || freebsd || (js && wasm) || wasip1 || (!android && linux) || netbsd || openbsd || solaris) && ((!cgo && !darwin) || osusergo)) || aix || illumos
package user
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build ((darwin || dragonfly || freebsd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && ((!cgo && !darwin) || osusergo)) || aix || illumos
+//go:build ((darwin || dragonfly || freebsd || (js && wasm) || wasip1 || (!android && linux) || netbsd || openbsd || solaris) && ((!cgo && !darwin) || osusergo)) || aix || illumos
package user
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build ((unix && !android) || (js && wasm)) && ((!cgo && !darwin) || osusergo)
+//go:build ((unix && !android) || (js && wasm) || wasip1) && ((!cgo && !darwin) || osusergo)
package user
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// aix, darwin, js/wasm, openbsd and solaris don't implement
+// aix, darwin, js/wasm, openbsd, solaris and wasip1/wasm don't implement
// waitid/wait6. netbsd implements wait6, but that is causing test
// failures, see issue #48789.
-//go:build aix || darwin || (js && wasm) || openbsd || solaris
+//go:build aix || darwin || (js && wasm) || openbsd || solaris || wasip1
package os