mirror of
https://github.com/wazero/wazero
synced 2026-06-21 14:12:37 +00:00
fs: allows non-root only mounts (#1047)
This adds syntax needed for wasi-testsuite, which mounts a path like below without mounting anything for "/". ``` -mount=./tests/c/testsuite/fs-tests.dir:/fs-tests.dir ``` Basically, this creates a virtual root path with fake stat. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -233,6 +233,13 @@ func TestRun(t *testing.T) {
|
||||
wazeroOpts: []string{fmt.Sprintf("--mount=%s:/:ro", bearDir)},
|
||||
stdOut: "pooh\n",
|
||||
},
|
||||
{
|
||||
name: "wasi non root",
|
||||
wasm: wasmCat,
|
||||
wazeroOpts: []string{fmt.Sprintf("--mount=%s:/animals:ro", bearDir)},
|
||||
wasmArgs: []string{"/animals/bear.txt"},
|
||||
stdOut: "pooh\n",
|
||||
},
|
||||
{
|
||||
name: "wasi logging",
|
||||
wasm: wasmWasiFd,
|
||||
|
||||
@@ -53,10 +53,9 @@ func NewRootFS(fs ...FS) (FS, error) {
|
||||
|
||||
// Ensure there is always a root match to keep runtime logic simpler.
|
||||
if ret.rootIndex == -1 {
|
||||
// TODO: Make a fake root filesystem that can do a directory listing of
|
||||
// any existing prefixes. We can't use UnimplementedFS as the pre-open
|
||||
// for root must work.
|
||||
return nil, fmt.Errorf("you must supply a root filesystem: %s", fsString(fs))
|
||||
ret.rootIndex = len(fs)
|
||||
ret.prefixes = append(ret.prefixes, "")
|
||||
ret.fs = append(ret.fs, fakeRootFS{})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -90,7 +89,7 @@ func fsString(fs []FS) string {
|
||||
func (c *CompositeFS) Unwrap() []FS {
|
||||
result := make([]FS, 0, len(c.fs))
|
||||
for i := len(c.fs) - 1; i >= 0; i-- {
|
||||
if fs := c.fs[i]; fs != (UnimplementedFS{}) {
|
||||
if fs := c.fs[i]; fs != (fakeRootFS{}) {
|
||||
result = append(result, fs)
|
||||
}
|
||||
}
|
||||
@@ -376,3 +375,35 @@ loop:
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type fakeRootFS struct{ UnimplementedFS }
|
||||
|
||||
// OpenFile implements FS.OpenFile
|
||||
func (fakeRootFS) OpenFile(path string, flag int, perm fs.FileMode) (fs.File, error) {
|
||||
switch path {
|
||||
case ".", "/", "":
|
||||
return fakeRootDir{}, nil
|
||||
}
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
type fakeRootDir struct{}
|
||||
|
||||
func (fakeRootDir) Close() (err error) { return }
|
||||
|
||||
func (fakeRootDir) Stat() (fs.FileInfo, error) { return fakeRootDirInfo{}, nil }
|
||||
|
||||
func (fakeRootDir) Read([]byte) (int, error) {
|
||||
return 0, &fs.PathError{Op: "read", Path: "/", Err: syscall.EISDIR}
|
||||
}
|
||||
|
||||
type fakeRootDirInfo struct{}
|
||||
|
||||
func (fakeRootDirInfo) Name() string { return "/" }
|
||||
func (fakeRootDirInfo) Size() int64 { return 0 }
|
||||
func (fakeRootDirInfo) Mode() fs.FileMode { return fs.ModeDir | 0o500 }
|
||||
func (fakeRootDirInfo) ModTime() time.Time { return time.Unix(0, 0) }
|
||||
func (fakeRootDirInfo) IsDir() bool { return true }
|
||||
func (fakeRootDirInfo) Sys() interface{} { return nil }
|
||||
|
||||
func (fakeRootDir) ReadDir(int) (dirents []fs.DirEntry, err error) { return }
|
||||
|
||||
@@ -34,12 +34,29 @@ func TestNewRootFS(t *testing.T) {
|
||||
// Should not be a composite filesystem
|
||||
require.Equal(t, testFS, rootFS)
|
||||
})
|
||||
t.Run("only non root unsupported", func(t *testing.T) {
|
||||
t.Run("only non root", func(t *testing.T) {
|
||||
testFS, err := NewDirFS(".", "/tmp")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = NewRootFS(testFS)
|
||||
require.EqualError(t, err, "you must supply a root filesystem: .:/tmp")
|
||||
rootFS, err := NewRootFS(testFS)
|
||||
require.NoError(t, err)
|
||||
|
||||
// String doesn't include the fake name
|
||||
require.Equal(t, ".:/tmp", rootFS.String())
|
||||
|
||||
// Guest can look up /tmp
|
||||
f, err := rootFS.OpenFile("/tmp", os.O_RDONLY, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
// Guest can look up / and see "/tmp" in it
|
||||
f, err = rootFS.OpenFile("/", os.O_RDONLY, 0)
|
||||
require.NoError(t, err)
|
||||
dirents, err := f.(fs.ReadDirFile).ReadDir(-1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(dirents))
|
||||
require.Equal(t, "tmp", dirents[0].Name())
|
||||
require.True(t, dirents[0].IsDir())
|
||||
})
|
||||
t.Run("multiple roots unsupported", func(t *testing.T) {
|
||||
testFS, err := NewDirFS(".", "/")
|
||||
|
||||
Reference in New Issue
Block a user