Repository: tetratelabs/wazero
Pull request #1236 (2023-03-14 02:35:55)

sysfs: maps syscall.EROFS
This passes the last test in gojs (except on my darwin host and windows ;))

```bash
$ wasm=$PWD/os.wasm; (cd $(go env GOROOT)/src/os; wazero run -mount=/:/ --experimental-workdir-inherit=true $wasm)
--- FAIL: TestOpenFileLimit (0.01s)
    rlimit_test.go:31: open rlimit.go: I/O error
FAIL
```


Patch:
diff --git a/internal/gojs/errno.go b/internal/gojs/errno.go
index d4ba7192..24d8b179 100644
--- a/internal/gojs/errno.go
+++ b/internal/gojs/errno.go
@@ -54,6 +54,8 @@ var (
 	ErrnoNotsup = &Errno{"ENOTSUP"}
 	// ErrnoPerm Operation not permitted.
 	ErrnoPerm = &Errno{"EPERM"}
+	// ErrnoRofs read-only file system.
+	ErrnoRofs = &Errno{"EROFS"}
 )
 
 // ToErrno maps I/O errors as the message must be the code, ex. "EINVAL", not
@@ -99,6 +101,8 @@ func ToErrno(err error) *Errno {
 		return ErrnoNotsup
 	case syscall.EPERM:
 		return ErrnoPerm
+	case syscall.EROFS:
+		return ErrnoRofs
 	default:
 		return ErrnoIo
 	}
diff --git a/internal/sysfs/readfs.go b/internal/sysfs/readfs.go
index 66f57863..ec1accd7 100644
--- a/internal/sysfs/readfs.go
+++ b/internal/sysfs/readfs.go
@@ -23,7 +23,6 @@ func NewReadFS(fs FS) FS {
 }
 
 type readFS struct {
-	UnimplementedFS
 	fs FS
 }
 
@@ -155,3 +154,58 @@ func (r *readFS) Stat(path string, stat *platform.Stat_t) error {
 func (r *readFS) Readlink(path string) (dst string, err error) {
 	return r.fs.Readlink(path)
 }
+
+// Mkdir implements FS.Mkdir
+func (r *readFS) Mkdir(path string, perm fs.FileMode) error {
+	return syscall.EROFS
+}
+
+// Chmod implements FS.Chmod
+func (r *readFS) Chmod(path string, perm fs.FileMode) error {
+	return syscall.EROFS
+}
+
+// Chown implements FS.Chown
+func (r *readFS) Chown(path string, uid, gid int) error {
+	return syscall.EROFS
+}
+
+// Lchown implements FS.Lchown
+func (r *readFS) Lchown(path string, uid, gid int) error {
+	return syscall.EROFS
+}
+
+// Rename implements FS.Rename
+func (r *readFS) Rename(from, to string) error {
+	return syscall.EROFS
+}
+
+// Rmdir implements FS.Rmdir
+func (r *readFS) Rmdir(path string) error {
+	return syscall.EROFS
+}
+
+// Link implements FS.Link
+func (r *readFS) Link(_, _ string) error {
+	return syscall.EROFS
+}
+
+// Symlink implements FS.Symlink
+func (r *readFS) Symlink(_, _ string) error {
+	return syscall.EROFS
+}
+
+// Unlink implements FS.Unlink
+func (r *readFS) Unlink(path string) error {
+	return syscall.EROFS
+}
+
+// Utimens implements FS.Utimens
+func (r *readFS) Utimens(path string, times *[2]syscall.Timespec, symlinkFollow bool) error {
+	return syscall.EROFS
+}
+
+// Truncate implements FS.Truncate
+func (r *readFS) Truncate(string, int64) error {
+	return syscall.EROFS
+}
diff --git a/internal/sysfs/unsupported.go b/internal/sysfs/unsupported.go
index 8e3cd40f..8aa21dae 100644
--- a/internal/sysfs/unsupported.go
+++ b/internal/sysfs/unsupported.go
@@ -36,6 +36,11 @@ func (UnimplementedFS) Stat(path string, stat *platform.Stat_t) error {
 	return syscall.ENOSYS
 }
 
+// Readlink implements FS.Readlink
+func (UnimplementedFS) Readlink(path string) (string, error) {
+	return "", syscall.ENOSYS
+}
+
 // Mkdir implements FS.Mkdir
 func (UnimplementedFS) Mkdir(path string, perm fs.FileMode) error {
 	return syscall.ENOSYS
@@ -66,11 +71,6 @@ func (UnimplementedFS) Rmdir(path string) error {
 	return syscall.ENOSYS
 }
 
-// Readlink implements FS.Readlink
-func (UnimplementedFS) Readlink(path string) (string, error) {
-	return "", syscall.ENOSYS
-}
-
 // Link implements FS.Link
 func (UnimplementedFS) Link(_, _ string) error {
 	return syscall.ENOSYS
diff --git a/internal/wasi_snapshot_preview1/errno.go b/internal/wasi_snapshot_preview1/errno.go
index 3b59a240..d29ea10c 100644
--- a/internal/wasi_snapshot_preview1/errno.go
+++ b/internal/wasi_snapshot_preview1/errno.go
@@ -305,6 +305,8 @@ func ToErrno(err error) Errno {
 		return ErrnoNotsup
 	case syscall.EPERM:
 		return ErrnoPerm
+	case syscall.EROFS:
+		return ErrnoRofs
 	default:
 		return ErrnoIo
 	}


Test patch:
diff --git a/internal/gojs/errno_test.go b/internal/gojs/errno_test.go
index 3166f901..266a6e0b 100644
--- a/internal/gojs/errno_test.go
+++ b/internal/gojs/errno_test.go
@@ -99,6 +99,11 @@ func TestToErrno(t *testing.T) {
 			input:    syscall.EPERM,
 			expected: ErrnoPerm,
 		},
+		{
+			name:     "syscall.EROFS",
+			input:    syscall.EROFS,
+			expected: ErrnoRofs,
+		},
 		{
 			name:     "syscall.Errno unexpected == ErrnoIo",
 			input:    syscall.Errno(0xfe),
diff --git a/internal/sysfs/readfs_test.go b/internal/sysfs/readfs_test.go
index 5bd29918..5c9b5b68 100644
--- a/internal/sysfs/readfs_test.go
+++ b/internal/sysfs/readfs_test.go
@@ -54,7 +54,7 @@ func TestReadFS_MkDir(t *testing.T) {
 	testFS := NewReadFS(writeable)
 
 	err := testFS.Mkdir("mkdir", fs.ModeDir)
-	require.EqualErrno(t, syscall.ENOSYS, err)
+	require.EqualErrno(t, syscall.EROFS, err)
 }
 
 func TestReadFS_Chmod(t *testing.T) {
@@ -62,7 +62,7 @@ func TestReadFS_Chmod(t *testing.T) {
 	testFS := NewReadFS(writeable)
 
 	err := testFS.Chmod("chmod", fs.ModeDir)
-	require.EqualErrno(t, syscall.ENOSYS, err)
+	require.EqualErrno(t, syscall.EROFS, err)
 }
 
 func TestReadFS_Rename(t *testing.T) {
@@ -83,7 +83,7 @@ func TestReadFS_Rename(t *testing.T) {
 	require.NoError(t, err)
 
 	err = testFS.Rename(file1, file2)
-	require.EqualErrno(t, syscall.ENOSYS, err)
+	require.EqualErrno(t, syscall.EROFS, err)
 }
 
 func TestReadFS_Rmdir(t *testing.T) {
@@ -96,7 +96,7 @@ func TestReadFS_Rmdir(t *testing.T) {
 	require.NoError(t, os.Mkdir(realPath, 0o700))
 
 	err := testFS.Rmdir(path)
-	require.EqualErrno(t, syscall.ENOSYS, err)
+	require.EqualErrno(t, syscall.EROFS, err)
 }
 
 func TestReadFS_Unlink(t *testing.T) {
@@ -109,7 +109,7 @@ func TestReadFS_Unlink(t *testing.T) {
 	require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
 	err := testFS.Unlink(path)
-	require.EqualErrno(t, syscall.ENOSYS, err)
+	require.EqualErrno(t, syscall.EROFS, err)
 }
 
 func TestReadFS_UtimesNano(t *testing.T) {
@@ -122,7 +122,7 @@ func TestReadFS_UtimesNano(t *testing.T) {
 	require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
 	err := testFS.Utimens(path, nil, true)
-	require.EqualErrno(t, syscall.ENOSYS, err)
+	require.EqualErrno(t, syscall.EROFS, err)
 }
 
 func TestReadFS_Open_Read(t *testing.T) {
diff --git a/internal/wasi_snapshot_preview1/errno_test.go b/internal/wasi_snapshot_preview1/errno_test.go
index dcedab40..4ac7e341 100644
--- a/internal/wasi_snapshot_preview1/errno_test.go
+++ b/internal/wasi_snapshot_preview1/errno_test.go
@@ -101,6 +101,11 @@ func TestToErrno(t *testing.T) {
 			input:    syscall.EPERM,
 			expected: ErrnoPerm,
 		},
+		{
+			name:     "syscall.EROFS",
+			input:    syscall.EROFS,
+			expected: ErrnoRofs,
+		},
 		{
 			name:     "syscall.EqualErrno unexpected == ErrnoIo",
 			input:    syscall.Errno(0xfe),