Removes platform.Readdirnames (#1451)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -324,12 +324,12 @@ func syscallReaddir(_ context.Context, mod api.Module, name string) (*objectArra
|
||||
}
|
||||
defer f.Close() //nolint
|
||||
|
||||
if names, errno := platform.Readdirnames(f.File(), -1); errno != 0 {
|
||||
if dirents, errno := platform.Readdir(f.File(), -1); errno != 0 {
|
||||
return nil, errno
|
||||
} else {
|
||||
entries := make([]interface{}, 0, len(names))
|
||||
for _, e := range names {
|
||||
entries = append(entries, e)
|
||||
entries := make([]interface{}, 0, len(dirents))
|
||||
for _, e := range dirents {
|
||||
entries = append(entries, e.Name)
|
||||
}
|
||||
return &objectArray{entries}, nil
|
||||
}
|
||||
|
||||
@@ -7,43 +7,6 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Readdirnames reads the names of the directory associated with file and
|
||||
// returns a slice of up to n strings in an arbitrary order. This is a stateful
|
||||
// function, so subsequent calls return any next values.
|
||||
//
|
||||
// If n > 0, Readdirnames returns at most n entries or an error.
|
||||
// If n <= 0, Readdirnames returns all remaining entries or an error.
|
||||
//
|
||||
// # Errors
|
||||
//
|
||||
// A zero syscall.Errno is success.
|
||||
//
|
||||
// For portability reasons, no error is returned on io.EOF, when the file is
|
||||
// closed or removed while open.
|
||||
// See https://github.com/ziglang/zig/blob/0.10.1/lib/std/fs.zig#L635-L637
|
||||
func Readdirnames(f fs.File, n int) (names []string, errno syscall.Errno) {
|
||||
switch f := f.(type) {
|
||||
case readdirnamesFile:
|
||||
var err error
|
||||
names, err = f.Readdirnames(n)
|
||||
if errno = adjustReaddirErr(err); errno != 0 {
|
||||
return
|
||||
}
|
||||
case fs.ReadDirFile:
|
||||
entries, err := f.ReadDir(n)
|
||||
if errno = adjustReaddirErr(err); errno != 0 {
|
||||
return
|
||||
}
|
||||
names = make([]string, 0, len(entries))
|
||||
for _, e := range entries {
|
||||
names = append(names, e.Name())
|
||||
}
|
||||
default:
|
||||
errno = syscall.ENOTDIR
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Dirent is an entry read from a directory.
|
||||
//
|
||||
// This is a portable variant of syscall.Dirent containing fields needed for
|
||||
|
||||
@@ -14,99 +14,6 @@ import (
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
)
|
||||
|
||||
func TestReaddirnames(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
require.NoError(t, fstest.WriteTestFiles(tmpDir))
|
||||
dirFS := os.DirFS(tmpDir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fs fs.FS
|
||||
}{
|
||||
{name: "os.DirFS", fs: dirFS}, // To test readdirnamesFile
|
||||
{name: "fstest.MapFS", fs: fstest.FS}, // To test adaptation of ReadDirFile
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
dotF, err := tc.fs.Open(".")
|
||||
require.NoError(t, err)
|
||||
defer dotF.Close()
|
||||
|
||||
t.Run("dir", func(t *testing.T) {
|
||||
names, errno := platform.Readdirnames(dotF, -1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
|
||||
sort.Strings(names)
|
||||
require.Equal(t, []string{"animals.txt", "dir", "empty.txt", "emptydir", "sub"}, names)
|
||||
|
||||
// read again even though it is exhausted
|
||||
_, errno = platform.Readdirnames(dotF, 100)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
})
|
||||
|
||||
// Don't err if something else closed the directory while reading.
|
||||
t.Run("closed dir", func(t *testing.T) {
|
||||
require.NoError(t, dotF.Close())
|
||||
_, errno := platform.Readdir(dotF, -1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
})
|
||||
|
||||
dirF, err := tc.fs.Open("dir")
|
||||
require.NoError(t, err)
|
||||
defer dirF.Close()
|
||||
|
||||
t.Run("partial", func(t *testing.T) {
|
||||
names1, errno := platform.Readdirnames(dirF, 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
require.Equal(t, 1, len(names1))
|
||||
|
||||
names2, errno := platform.Readdirnames(dirF, 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
require.Equal(t, 1, len(names2))
|
||||
|
||||
// read exactly the last entry
|
||||
names3, errno := platform.Readdirnames(dirF, 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
require.Equal(t, 1, len(names3))
|
||||
|
||||
names := []string{names1[0], names2[0], names3[0]}
|
||||
sort.Strings(names)
|
||||
|
||||
require.Equal(t, []string{"-", "a-", "ab-"}, names)
|
||||
|
||||
// no error reading an exhausted directory
|
||||
_, errno = platform.Readdirnames(dirF, 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
})
|
||||
|
||||
fileF, err := tc.fs.Open("empty.txt")
|
||||
require.NoError(t, err)
|
||||
defer fileF.Close()
|
||||
|
||||
t.Run("file", func(t *testing.T) {
|
||||
_, errno := platform.Readdirnames(fileF, -1)
|
||||
require.EqualErrno(t, syscall.ENOTDIR, errno)
|
||||
})
|
||||
|
||||
subdirF, err := tc.fs.Open("sub")
|
||||
require.NoError(t, err)
|
||||
defer subdirF.Close()
|
||||
|
||||
t.Run("subdir", func(t *testing.T) {
|
||||
names, errno := platform.Readdirnames(subdirF, -1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
|
||||
require.Equal(t, []string{"test.txt"}, names)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaddir(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -743,7 +743,6 @@ func (f *fsFile) File() fs.File {
|
||||
// ReadFile declares all read interfaces defined on os.File used by wazero.
|
||||
type ReadFile interface {
|
||||
fdFile // for the number of links.
|
||||
readdirnamesFile
|
||||
readdirFile
|
||||
fs.ReadDirFile
|
||||
io.ReaderAt // for pread
|
||||
@@ -768,10 +767,6 @@ type (
|
||||
}
|
||||
// fdFile is implemented by os.File in file_unix.go and file_windows.go
|
||||
fdFile interface{ Fd() (fd uintptr) }
|
||||
// readdirnamesFile is implemented by os.File in dir.go
|
||||
readdirnamesFile interface {
|
||||
Readdirnames(n int) (names []string, err error)
|
||||
}
|
||||
// readdirFile is implemented by os.File in dir.go
|
||||
readdirFile interface {
|
||||
Readdir(n int) ([]fs.FileInfo, error)
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
gofstest "testing/fstest"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/fstest"
|
||||
"github.com/tetratelabs/wazero/internal/platform"
|
||||
testfs "github.com/tetratelabs/wazero/internal/testing/fs"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
)
|
||||
@@ -111,18 +110,19 @@ func TestNewRootFS(t *testing.T) {
|
||||
require.EqualErrno(t, 0, errno)
|
||||
defer f.Close()
|
||||
|
||||
require.Equal(t, []string{"a", "tmp"}, readDirNames(t, f.File()))
|
||||
entries, err := f.File().(fs.ReadDirFile).ReadDir(-1)
|
||||
require.NoError(t, err)
|
||||
names := make([]string, 0, len(entries))
|
||||
for _, e := range entries {
|
||||
names = append(names, e.Name())
|
||||
}
|
||||
sort.Strings(names)
|
||||
|
||||
require.Equal(t, []string{"a", "tmp"}, names)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func readDirNames(t *testing.T, f fs.File) []string {
|
||||
names, errno := platform.Readdirnames(f, -1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
|
||||
func TestRootFS_String(t *testing.T) {
|
||||
tmpFS := NewDirFS(".")
|
||||
rootFS := NewDirFS(".")
|
||||
|
||||
@@ -92,15 +92,6 @@ func testOpen_Read(t *testing.T, testFS FS, expectIno bool) {
|
||||
}, dirents)
|
||||
})
|
||||
|
||||
t.Run("readdirnames . opens root", func(t *testing.T) {
|
||||
f, errno := testFS.OpenFile(".", os.O_RDONLY, 0)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
defer f.Close()
|
||||
|
||||
names := requireReaddirnames(t, f.File(), -1)
|
||||
require.Equal(t, []string{"animals.txt", "dir", "empty.txt", "emptydir", "sub"}, names)
|
||||
})
|
||||
|
||||
t.Run("readdir empty", func(t *testing.T) {
|
||||
f, errno := testFS.OpenFile("emptydir", os.O_RDONLY, 0)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
@@ -110,15 +101,6 @@ func testOpen_Read(t *testing.T, testFS FS, expectIno bool) {
|
||||
require.Zero(t, len(entries))
|
||||
})
|
||||
|
||||
t.Run("readdirnames empty", func(t *testing.T) {
|
||||
f, errno := testFS.OpenFile("emptydir", os.O_RDONLY, 0)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
defer f.Close()
|
||||
|
||||
names := requireReaddirnames(t, f.File(), -1)
|
||||
require.Zero(t, len(names))
|
||||
})
|
||||
|
||||
t.Run("readdir partial", func(t *testing.T) {
|
||||
dirF, errno := testFS.OpenFile("dir", os.O_RDONLY, 0)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
@@ -153,36 +135,6 @@ func testOpen_Read(t *testing.T, testFS FS, expectIno bool) {
|
||||
require.EqualErrno(t, 0, errno)
|
||||
})
|
||||
|
||||
// TODO: consolidate duplicated tests from platform once we have our own
|
||||
// file type
|
||||
t.Run("readdirnames partial", func(t *testing.T) {
|
||||
dirF, errno := testFS.OpenFile("dir", os.O_RDONLY, 0)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
defer dirF.Close()
|
||||
|
||||
names1, errno := platform.Readdirnames(dirF.File(), 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
require.Equal(t, 1, len(names1))
|
||||
|
||||
names2, errno := platform.Readdirnames(dirF.File(), 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
require.Equal(t, 1, len(names2))
|
||||
|
||||
// read exactly the last entry
|
||||
names3, errno := platform.Readdirnames(dirF.File(), 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
require.Equal(t, 1, len(names3))
|
||||
|
||||
names := []string{names1[0], names2[0], names3[0]}
|
||||
sort.Strings(names)
|
||||
|
||||
require.Equal(t, []string{"-", "a-", "ab-"}, names)
|
||||
|
||||
// no error reading an exhausted directory
|
||||
_, errno = platform.Readdirnames(dirF.File(), 1)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
})
|
||||
|
||||
t.Run("file exists", func(t *testing.T) {
|
||||
f, errno := testFS.OpenFile("animals.txt", os.O_RDONLY, 0)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
@@ -353,15 +305,6 @@ func requireReaddir(t *testing.T, f fs.File, n int, expectIno bool) []*platform.
|
||||
return entries
|
||||
}
|
||||
|
||||
// requireReaddirnames ensures the input file is a directory, and returns its
|
||||
// entries.
|
||||
func requireReaddirnames(t *testing.T, f fs.File, n int) []string {
|
||||
names, errno := platform.Readdirnames(f, n)
|
||||
require.EqualErrno(t, 0, errno)
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
|
||||
func testReadlink(t *testing.T, readFS, writeFS FS) {
|
||||
testLinks := []struct {
|
||||
old, dst string
|
||||
|
||||
Reference in New Issue
Block a user