Repository: tetratelabs/wazero (go)

Issue:
wasi: openFlags() handles flags exclusive

In [openFlags()](https://github.com/tetratelabs/wazero/blob/main/imports/wasi_snapshot_preview1/fs.go#L1373),
if both `trunc` and `creat` are given, only `creat` is applied and existing files are not truncated:

```go
	if oflags&O_TRUNC != 0 {
		openFlags = os.O_RDWR | os.O_TRUNC
	}
	if oflags&O_CREAT != 0 {
		openFlags = os.O_RDWR | os.O_CREATE
	}
	if fdflags&FD_APPEND != 0 {
		openFlags = os.O_RDWR | os.O_APPEND
	}
```
I assume it was ment to be `openFlags |= ..`

**Environment (please complete the relevant information):**
- Go version: [1.19.1]
- wazero Version: [d57bdecadbe577e1e6a112342b688826c7023f80]
- Host architecture: [amd64]
- Runtime mode: [cmd/wazero]




Pull request:
wasi: fixes flag logic that didn't OR correctly
fixes #1068

Patch:
diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go
index de3652a1..dc3113fc 100644
--- a/imports/wasi_snapshot_preview1/fs.go
+++ b/imports/wasi_snapshot_preview1/fs.go
@@ -6,8 +6,8 @@ import (
 	"io"
 	"io/fs"
 	"math"
-	"os"
 	pathutil "path"
+	"syscall"
 
 	"github.com/tetratelabs/wazero/api"
 	"github.com/tetratelabs/wazero/internal/platform"
@@ -1373,22 +1373,22 @@ func preopenPath(fsc *sys.FSContext, dirFD uint32) (string, Errno) {
 func openFlags(oflags, fdflags uint16) (openFlags int, isDir bool) {
 	isDir = oflags&O_DIRECTORY != 0
 	if oflags&O_TRUNC != 0 {
-		openFlags = os.O_RDWR | os.O_TRUNC
+		openFlags |= syscall.O_RDWR | syscall.O_TRUNC
 	}
 	if oflags&O_CREAT != 0 {
-		openFlags = os.O_RDWR | os.O_CREATE
+		openFlags |= syscall.O_RDWR | syscall.O_CREAT
 	}
 	if fdflags&FD_APPEND != 0 {
-		openFlags = os.O_RDWR | os.O_APPEND
+		openFlags |= syscall.O_RDWR | syscall.O_APPEND
 	}
 	if openFlags == 0 {
-		openFlags = os.O_RDONLY
+		openFlags = syscall.O_RDONLY
 	}
 	if isDir {
 		return
 	}
 	if oflags&O_EXCL != 0 {
-		openFlags |= os.O_EXCL
+		openFlags |= syscall.O_EXCL
 	}
 	return
 }


Test patch:
diff --git a/imports/wasi_snapshot_preview1/fs_unit_test.go b/imports/wasi_snapshot_preview1/fs_unit_test.go
index 107e1dd7..4567a5c1 100644
--- a/imports/wasi_snapshot_preview1/fs_unit_test.go
+++ b/imports/wasi_snapshot_preview1/fs_unit_test.go
@@ -3,6 +3,7 @@ package wasi_snapshot_preview1
 import (
 	"io"
 	"io/fs"
+	"syscall"
 	"testing"
 
 	"github.com/tetratelabs/wazero/internal/fstest"
@@ -350,3 +351,58 @@ func Test_writeDirents(t *testing.T) {
 		})
 	}
 }
+
+func Test_openFlags(t *testing.T) {
+	tests := []struct {
+		name              string
+		oflags, fdflags   uint16
+		expectedOpenFlags int
+		expectedIsDir     bool
+	}{
+		{
+			name:              "oflags=0",
+			expectedOpenFlags: syscall.O_RDONLY,
+		},
+		{
+			name:              "oflags=O_CREAT",
+			oflags:            O_CREAT,
+			expectedOpenFlags: syscall.O_RDWR | syscall.O_CREAT,
+		},
+		{
+			name:              "oflags=O_DIRECTORY",
+			oflags:            O_DIRECTORY,
+			expectedOpenFlags: syscall.O_RDONLY,
+			expectedIsDir:     true,
+		},
+		{
+			name:              "oflags=O_EXCL",
+			oflags:            O_EXCL,
+			expectedOpenFlags: syscall.O_RDONLY | syscall.O_EXCL,
+		},
+		{
+			name:              "oflags=O_TRUNC",
+			oflags:            O_TRUNC,
+			expectedOpenFlags: syscall.O_RDWR | syscall.O_TRUNC,
+		},
+		{
+			name:              "fdflags=FD_APPEND",
+			fdflags:           FD_APPEND,
+			expectedOpenFlags: syscall.O_RDWR | syscall.O_APPEND,
+		},
+		{
+			name:              "oflags=O_TRUNC|O_CREAT",
+			oflags:            O_TRUNC | O_CREAT,
+			expectedOpenFlags: syscall.O_RDWR | syscall.O_TRUNC | syscall.O_CREAT,
+		},
+	}
+
+	for _, tt := range tests {
+		tc := tt
+
+		t.Run(tc.name, func(t *testing.T) {
+			openFlags, isDir := openFlags(tc.oflags, tc.fdflags)
+			require.Equal(t, tc.expectedOpenFlags, openFlags)
+			require.Equal(t, tc.expectedIsDir, isDir)
+		})
+	}
+}