diff --git a/go.mod b/go.mod index 539c723bddf..aeea13fa7d2 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.28.0 github.com/testcontainers/testcontainers-go/modules/localstack v0.26.0 - github.com/tetratelabs/wazero v1.2.1 + github.com/tetratelabs/wazero v1.6.0 github.com/twitchtv/twirp v8.1.2+incompatible github.com/xeipuuv/gojsonschema v1.2.0 github.com/xlab/treeprint v1.2.0 diff --git a/go.sum b/go.sum index ba486cb5020..6319723f6b2 100644 --- a/go.sum +++ b/go.sum @@ -1629,8 +1629,8 @@ github.com/testcontainers/testcontainers-go v0.23.0 h1:ERYTSikX01QczBLPZpqsETTBO github.com/testcontainers/testcontainers-go v0.23.0/go.mod h1:3gzuZfb7T9qfcH2pHpV4RLlWrPjeWNQah6XlYQ32c4I= github.com/testcontainers/testcontainers-go/modules/localstack v0.26.0 h1:lpL04dHA9mGFBQLFcV+aEEh1Tf4ohXdIGgoj3J0bacM= github.com/testcontainers/testcontainers-go/modules/localstack v0.26.0/go.mod h1:1xkZPpkBu6coI7CyVn3DXUBnsVrZ+fd/Cc8lx6zk2mk= -github.com/tetratelabs/wazero v1.2.1 h1:J4X2hrGzJvt+wqltuvcSjHQ7ujQxA9gb6PeMs4qlUWs= -github.com/tetratelabs/wazero v1.2.1/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ= +github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g= +github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/twitchtv/twirp v8.1.2+incompatible h1:0O6TfzZW09ZP5r+ORA90XQEE3PTgA6C7MBbl2KxvVgE= diff --git a/pkg/module/memfs.go b/pkg/module/memfs.go index 0a3b37452f9..d407fd21e88 100644 --- a/pkg/module/memfs.go +++ b/pkg/module/memfs.go @@ -4,6 +4,7 @@ import ( "io" "io/fs" "path/filepath" + "time" "golang.org/x/xerrors" @@ -19,10 +20,14 @@ type memFS struct { // Open implements fs.FS. func (m *memFS) Open(name string) (fs.File, error) { - if m.current == nil { - return nil, fs.ErrNotExist + if m.current != nil { + return m.current.Open(name) } - return m.current.Open(name) + // memFS is always a directory. + if name == "." { + return &emptyDir{}, nil + } + return nil, fs.ErrNotExist } // initialize changes the underlying memory file system with the given file path and contents. @@ -46,3 +51,21 @@ func (m *memFS) initialize(filePath string, content xio.ReadSeekerAt) error { m.current = mfs return nil } + +type emptyDir struct{} + +func (emptyDir) Close() (err error) { return } +func (emptyDir) Stat() (fs.FileInfo, error) { return fakeRootDirInfo{}, nil } +func (emptyDir) Read([]byte) (int, error) { + return 0, &fs.PathError{Op: "read", Path: "/", Err: fs.ErrInvalid} +} + +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 (emptyDir) ReadDir(int) (dirents []fs.DirEntry, err error) { return } diff --git a/pkg/module/memfs_test.go b/pkg/module/memfs_test.go index 584efa1d7c6..fe60004cb78 100644 --- a/pkg/module/memfs_test.go +++ b/pkg/module/memfs_test.go @@ -1,7 +1,9 @@ package module import ( + "errors" "io" + "io/fs" "os" "strings" "testing" @@ -31,3 +33,27 @@ func TestMemFS(t *testing.T) { require.ErrorIs(t, err, os.ErrNotExist) }) } + +func TestMemFS_NilIsDirectory(t *testing.T) { + // Wasm module initializes before an FS has been + // associated to this memFS. We handle nil + // so that the guest knows that the mount will map + // to a directory in the future. + m := &memFS{} + require.Nil(t, m.current) + + f, err := m.Open(".") + require.NoError(t, err) + + t.Run("stat is dir", func(t *testing.T) { + st, err := f.Stat() + require.NoError(t, err) + require.True(t, st.IsDir()) + }) + + t.Run("read invalid", func(t *testing.T) { + buf := make([]byte, 4) + _, err = f.Read(buf) + require.True(t, errors.Is(err, fs.ErrInvalid)) + }) +}