Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fsapi: adds Oflag to decouple from syscall package #1586

Merged
merged 1 commit into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion experimental/sys/errno.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Errno uint16
// the Errno it returns, and we export fs.FS. This is not in /internal/sys as
// that would introduce a package cycle.

// This is a subset of errors to reduce implementation burden. `wasip` defines
// This is a subset of errors to reduce implementation burden. `wasip1` defines
// almost all POSIX error numbers, but not all are used in practice. wazero
// will add ones needed in POSIX order, as needed by functions that explicitly
// document returning them.
Expand Down
38 changes: 24 additions & 14 deletions imports/wasi_snapshot_preview1/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1687,53 +1687,63 @@ func preopenPath(fsc *sys.FSContext, fd int32) (string, experimentalsys.Errno) {
}
}

func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags int) {
func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags fsapi.Oflag) {
if dirflags&wasip1.LOOKUP_SYMLINK_FOLLOW == 0 {
openFlags |= fsapi.O_NOFOLLOW
}
if oflags&wasip1.O_DIRECTORY != 0 {
openFlags |= fsapi.O_DIRECTORY
return // Early return for directories as the rest of flags doesn't make sense for it.
} else if oflags&wasip1.O_EXCL != 0 {
openFlags |= syscall.O_EXCL
openFlags |= fsapi.O_EXCL
}
// Because we don't implement rights, we paritally rely on the open flags
// Because we don't implement rights, we partially rely on the open flags
// to determine the mode in which the file will be opened. This will create
// divergent behavior compared to WASI runtimes which have a more strict
// interpretation of the WASI capabilities model; for example, a program
// which sets O_CREAT but does not give read or write permissions will
// successfully create a file when running with wazero, but might get a
// permission denied error on other runtimes.
defaultMode := syscall.O_RDONLY
defaultMode := fsapi.O_RDONLY
if oflags&wasip1.O_TRUNC != 0 {
openFlags |= syscall.O_TRUNC
defaultMode = syscall.O_RDWR
openFlags |= fsapi.O_TRUNC
defaultMode = fsapi.O_RDWR
}
if oflags&wasip1.O_CREAT != 0 {
openFlags |= syscall.O_CREAT
defaultMode = syscall.O_RDWR
openFlags |= fsapi.O_CREAT
defaultMode = fsapi.O_RDWR
}
if fdflags&wasip1.FD_NONBLOCK != 0 {
openFlags |= fsapi.O_NONBLOCK
}
if fdflags&wasip1.FD_APPEND != 0 {
openFlags |= syscall.O_APPEND
defaultMode = syscall.O_RDWR
openFlags |= fsapi.O_APPEND
defaultMode = fsapi.O_RDWR
}
if fdflags&wasip1.FD_DSYNC != 0 {
openFlags |= fsapi.O_DSYNC
}
if fdflags&wasip1.FD_RSYNC != 0 {
openFlags |= fsapi.O_RSYNC
}
if fdflags&wasip1.FD_SYNC != 0 {
openFlags |= fsapi.O_SYNC
}

// Since rights were discontinued in wasi, we only interpret RIGHT_FD_WRITE
// because it is the only way to know that we need to set write permissions
// on a file if the application did not pass any of O_CREATE, O_APPEND, nor
// on a file if the application did not pass any of O_CREAT, O_APPEND, nor
// O_TRUNC.
const r = wasip1.RIGHT_FD_READ
const w = wasip1.RIGHT_FD_WRITE
const rw = r | w
switch {
case (rights & rw) == rw:
openFlags |= syscall.O_RDWR
openFlags |= fsapi.O_RDWR
case (rights & w) == w:
openFlags |= syscall.O_WRONLY
openFlags |= fsapi.O_WRONLY
case (rights & r) == r:
openFlags |= syscall.O_RDONLY
openFlags |= fsapi.O_RDONLY
default:
openFlags |= defaultMode
}
Expand Down
53 changes: 26 additions & 27 deletions imports/wasi_snapshot_preview1/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"path"
"runtime"
"strings"
"syscall"
"testing"
gofstest "testing/fstest"
"time"
Expand Down Expand Up @@ -60,7 +59,7 @@ func Test_fdAllocate(t *testing.T) {
preopen := fsc.RootFS()
defer r.Close(testCtx)

fd, errno := fsc.OpenFile(preopen, fileName, os.O_RDWR, 0)
fd, errno := fsc.OpenFile(preopen, fileName, fsapi.O_RDWR, 0)
require.EqualErrno(t, 0, errno)

f, ok := fsc.LookupFile(fd)
Expand Down Expand Up @@ -138,10 +137,10 @@ func Test_fdClose(t *testing.T) {
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()

fdToClose, errno := fsc.OpenFile(preopen, path1, os.O_RDONLY, 0)
fdToClose, errno := fsc.OpenFile(preopen, path1, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

fdToKeep, errno := fsc.OpenFile(preopen, path2, os.O_RDONLY, 0)
fdToKeep, errno := fsc.OpenFile(preopen, path2, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

// Close
Expand Down Expand Up @@ -253,10 +252,10 @@ func Test_fdFdstatGet(t *testing.T) {
stdin.File = stdinFile

// Make this file writeable, to ensure flags read-back correctly.
fileFD, errno := fsc.OpenFile(preopen, file, os.O_RDWR, 0)
fileFD, errno := fsc.OpenFile(preopen, file, fsapi.O_RDWR, 0)
require.EqualErrno(t, 0, errno)

dirFD, errno := fsc.OpenFile(preopen, dir, os.O_RDONLY, 0)
dirFD, errno := fsc.OpenFile(preopen, dir, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

tests := []struct {
Expand Down Expand Up @@ -503,12 +502,12 @@ func Test_fdFdstatSetFlags(t *testing.T) {
preopen := fsc.RootFS()
defer r.Close(testCtx)

// First, O_CREATE the file with O_APPEND. We use O_EXCL because that
// triggers an EEXIST error if called a second time with O_CREATE. Our
// logic should clear O_CREATE preventing this.
// First, O_CREAT the file with O_APPEND. We use O_EXCL because that
// triggers an EEXIST error if called a second time with O_CREAT. Our
// logic should clear O_CREAT preventing this.
const fileName = "file.txt"
// Create the target file.
fd, errno := fsc.OpenFile(preopen, fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE|syscall.O_EXCL, 0o600)
fd, errno := fsc.OpenFile(preopen, fileName, fsapi.O_RDWR|fsapi.O_APPEND|fsapi.O_CREAT|fsapi.O_EXCL, 0o600)
require.EqualErrno(t, 0, errno)

// Write the initial text to the file.
Expand Down Expand Up @@ -615,10 +614,10 @@ func Test_fdFilestatGet(t *testing.T) {
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()

fileFD, errno := fsc.OpenFile(preopen, file, os.O_RDONLY, 0)
fileFD, errno := fsc.OpenFile(preopen, file, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

dirFD, errno := fsc.OpenFile(preopen, dir, os.O_RDONLY, 0)
dirFD, errno := fsc.OpenFile(preopen, dir, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

tests := []struct {
Expand Down Expand Up @@ -2157,7 +2156,7 @@ func Test_fdReaddir(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
defer log.Reset()

fd, errno := fsc.OpenFile(preopen, tc.initialDir, os.O_RDONLY, 0)
fd, errno := fsc.OpenFile(preopen, tc.initialDir, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
defer fsc.CloseFile(fd) // nolint

Expand Down Expand Up @@ -2199,7 +2198,7 @@ func Test_fdReaddir_Rewind(t *testing.T) {

fsc := mod.(*wasm.ModuleInstance).Sys.FS()

fd, errno := fsc.OpenFile(fsc.RootFS(), ".", os.O_RDONLY, 0)
fd, errno := fsc.OpenFile(fsc.RootFS(), ".", fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

mem := mod.Memory()
Expand Down Expand Up @@ -2248,7 +2247,7 @@ func Test_fdReaddir_Errors(t *testing.T) {
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()

fileFD, errno := fsc.OpenFile(preopen, "animals.txt", os.O_RDONLY, 0)
fileFD, errno := fsc.OpenFile(preopen, "animals.txt", fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

// Directories are stateful, so we open them during the test.
Expand Down Expand Up @@ -2352,7 +2351,7 @@ func Test_fdReaddir_Errors(t *testing.T) {

// Reset the directory so that tests don't taint each other.
if tc.fd == dirFD {
dirFD, errno = fsc.OpenFile(preopen, "dir", os.O_RDONLY, 0)
dirFD, errno = fsc.OpenFile(preopen, "dir", fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
defer fsc.CloseFile(dirFD) // nolint
}
Expand Down Expand Up @@ -2465,11 +2464,11 @@ func Test_fdRenumber(t *testing.T) {
preopen := fsc.RootFS()

// Sanity check of the file descriptor assignment.
fileFDAssigned, errno := fsc.OpenFile(preopen, "animals.txt", os.O_RDONLY, 0)
fileFDAssigned, errno := fsc.OpenFile(preopen, "animals.txt", fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
require.Equal(t, int32(fileFD), fileFDAssigned)

dirFDAssigned, errno := fsc.OpenFile(preopen, "dir", os.O_RDONLY, 0)
dirFDAssigned, errno := fsc.OpenFile(preopen, "dir", fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
require.Equal(t, int32(dirFD), dirFDAssigned)

Expand Down Expand Up @@ -3605,7 +3604,7 @@ func Test_pathLink(t *testing.T) {
uint64(newFd), uint64(destination), uint64(len(destinationName)))
require.Contains(t, log.String(), wasip1.ErrnoName(wasip1.ErrnoSuccess))

f := openFile(t, destinationRealPath, os.O_RDONLY, 0)
f := openFile(t, destinationRealPath, fsapi.O_RDONLY, 0)
defer f.Close()

st, errno := f.Stat()
Expand Down Expand Up @@ -3927,7 +3926,7 @@ func requireOpenFD(t *testing.T, mod api.Module, path string) int32 {
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()

fd, errno := fsc.OpenFile(preopen, path, os.O_RDONLY, 0)
fd, errno := fsc.OpenFile(preopen, path, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
return fd
}
Expand Down Expand Up @@ -4856,14 +4855,14 @@ func Test_pathUnlinkFile_Errors(t *testing.T) {
}

func requireOpenFile(t *testing.T, tmpDir string, pathName string, data []byte, readOnly bool) (api.Module, int32, *bytes.Buffer, api.Closer) {
oflags := os.O_RDWR
oflags := fsapi.O_RDWR
if readOnly {
oflags = os.O_RDONLY
oflags = fsapi.O_RDONLY
}

realPath := joinPath(tmpDir, pathName)
if data == nil {
oflags = os.O_RDONLY
oflags = fsapi.O_RDONLY
require.NoError(t, os.Mkdir(realPath, 0o700))
} else {
require.NoError(t, os.WriteFile(realPath, data, 0o600))
Expand Down Expand Up @@ -4910,7 +4909,7 @@ func Test_fdReaddir_dotEntryHasARealInode(t *testing.T) {
uint64(sys.FdPreopen), uint64(0), uint64(len(readDirTarget)))

// Open the directory, before writing files!
fd, errno := fsc.OpenFile(preopen, readDirTarget, os.O_RDONLY, 0)
fd, errno := fsc.OpenFile(preopen, readDirTarget, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

// get the real inode of the current directory
Expand Down Expand Up @@ -4968,11 +4967,11 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
uint64(sys.FdPreopen), uint64(0), uint64(len(dirName)))

// Open the directory, before writing files!
dirFD, errno := fsc.OpenFile(preopen, dirName, os.O_RDONLY, 0)
dirFD, errno := fsc.OpenFile(preopen, dirName, fsapi.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

// Then write a file to the directory.
f := openFile(t, joinPath(dirPath, "file"), os.O_CREATE, 0)
f := openFile(t, joinPath(dirPath, "file"), fsapi.O_CREAT, 0)
defer f.Close()

// get the real inode of the current directory
Expand Down Expand Up @@ -5021,7 +5020,7 @@ func joinPath(dirName, baseName string) string {
return path.Join(dirName, baseName)
}

func openFile(t *testing.T, path string, flag int, perm fs.FileMode) fsapi.File {
func openFile(t *testing.T, path string, flag fsapi.Oflag, perm fs.FileMode) fsapi.File {
f, errno := sysfs.OpenOSFile(path, flag, perm)
require.EqualErrno(t, 0, errno)
return f
Expand Down
25 changes: 12 additions & 13 deletions imports/wasi_snapshot_preview1/fs_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package wasi_snapshot_preview1

import (
"os"
"syscall"
"testing"

"github.com/tetratelabs/wazero/internal/fsapi"
Expand Down Expand Up @@ -110,7 +109,7 @@ func Test_maxDirents(t *testing.T) {
var (
testDirents = func() []fsapi.Dirent {
dPath := "dir"
d, errno := sysfs.OpenFSFile(fstest.FS, dPath, syscall.O_RDONLY, 0)
d, errno := sysfs.OpenFSFile(fstest.FS, dPath, fsapi.O_RDONLY, 0)
if errno != 0 {
panic(errno)
}
Expand Down Expand Up @@ -208,16 +207,16 @@ func Test_openFlags(t *testing.T) {
name string
dirflags, oflags, fdflags uint16
rights uint32
expectedOpenFlags int
expectedOpenFlags fsapi.Oflag
}{
{
name: "oflags=0",
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDONLY,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDONLY,
},
{
name: "oflags=O_CREAT",
oflags: wasip1.O_CREAT,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDWR | syscall.O_CREAT,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_CREAT,
},
{
name: "oflags=O_DIRECTORY",
Expand All @@ -227,42 +226,42 @@ func Test_openFlags(t *testing.T) {
{
name: "oflags=O_EXCL",
oflags: wasip1.O_EXCL,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDONLY | syscall.O_EXCL,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDONLY | fsapi.O_EXCL,
},
{
name: "oflags=O_TRUNC",
oflags: wasip1.O_TRUNC,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDWR | syscall.O_TRUNC,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_TRUNC,
},
{
name: "fdflags=FD_APPEND",
fdflags: wasip1.FD_APPEND,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDWR | syscall.O_APPEND,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_APPEND,
},
{
name: "oflags=O_TRUNC|O_CREAT",
oflags: wasip1.O_TRUNC | wasip1.O_CREAT,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDWR | syscall.O_TRUNC | syscall.O_CREAT,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_TRUNC | fsapi.O_CREAT,
},
{
name: "dirflags=LOOKUP_SYMLINK_FOLLOW",
dirflags: wasip1.LOOKUP_SYMLINK_FOLLOW,
expectedOpenFlags: syscall.O_RDONLY,
expectedOpenFlags: fsapi.O_RDONLY,
},
{
name: "rights=FD_READ",
rights: wasip1.RIGHT_FD_READ,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDONLY,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDONLY,
},
{
name: "rights=FD_WRITE",
rights: wasip1.RIGHT_FD_WRITE,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_WRONLY,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_WRONLY,
},
{
name: "rights=FD_READ|FD_WRITE",
rights: wasip1.RIGHT_FD_READ | wasip1.RIGHT_FD_WRITE,
expectedOpenFlags: fsapi.O_NOFOLLOW | syscall.O_RDWR,
expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR,
},
}

Expand Down
5 changes: 3 additions & 2 deletions imports/wasi_snapshot_preview1/wasi_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/tetratelabs/wazero/internal/fsapi"
"github.com/tetratelabs/wazero/internal/sys"
"github.com/tetratelabs/wazero/internal/testing/proxy"
"github.com/tetratelabs/wazero/internal/wasip1"
Expand Down Expand Up @@ -198,7 +199,7 @@ func Benchmark_fdReaddir(b *testing.B) {

// Open the root directory as a file-descriptor.
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
fd, errno := fsc.OpenFile(fsc.RootFS(), ".", os.O_RDONLY, 0)
fd, errno := fsc.OpenFile(fsc.RootFS(), ".", fsapi.O_RDONLY, 0)
if errno != 0 {
b.Fatal(errno)
}
Expand Down Expand Up @@ -307,7 +308,7 @@ func Benchmark_pathFilestat(b *testing.B) {
fd := sys.FdPreopen
if bc.fd != sys.FdPreopen {
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
fd, errno := fsc.OpenFile(fsc.RootFS(), "zig", os.O_RDONLY, 0)
fd, errno := fsc.OpenFile(fsc.RootFS(), "zig", fsapi.O_RDONLY, 0)
if errno != 0 {
b.Fatal(errno)
}
Expand Down
Loading