Repository: tetratelabs/wazero
Pull request #981 (2022-12-30 09:17:45)

wasi: fixes open flags
This fixes and backfills tests for open flags, notably O_CREAT. I verified this with TinyGo tests, which now proceed when attempting to create new files.

```bash
$ wazero run -hostlogging=filesystem -mount=.:/ os.wasm -test.v
==> wasi_snapshot_preview1.fd_prestat_get(fd=3)
<== (prestat={pr_name_len=1},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_prestat_dir_name(fd=3)
<== (path=/,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_prestat_get(fd=4)
<== (prestat=,errno=EBADF)
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/_os_test_TestTempDir)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/_os_test_TestTempDir)
<== errno=ENOENT
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/_os_test_TestTempDir,oflags=CREAT,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=4,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=4)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/_os_test_TestTempDir)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=_os_test_TestChDir)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=_os_test_TestChDir)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_create_directory(fd=3,path=_os_test_TestChDir)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=_os_test_TestChDir)
<== (filestat={filetype=DIRECTORY,size=64,mtim=1672391667958762313},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=_os_test_TestChDir/_os_test_TestTempDir.dat,oflags=CREAT,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=6,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=6)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=.)
<== (filestat={filetype=DIRECTORY,size=1664,mtim=1672391667958770230},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=_os_test_TestChDir/_os_test_TestTempDir.dat)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=_os_test_TestChDir)
<== errno=EISDIR
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=_os_test_TestChDir)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=_os_test_TestTempDir.dat)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=_os_test_TestTempDir.dat)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=_os_test_TestChDir)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=_os_test_TestChDir)
<== errno=ENOENT
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestFd.txt85364081,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=7,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=7,iovs=170104,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_pread(fd=7,iovs=170136,iovs_len=1,offset=0)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=7)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_close(fd=7)
<== errno=EBADF
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestFd.txt85364081)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_create_directory(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=EISDIR
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/TestMkdir18446744072750057615)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/not-exist/really-not-exist)
<== (filestat=,errno=ENOENT)
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestFstat,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=9,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=9,iovs=169832,iovs_len=1)
<== (nwritten=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=9)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestFstat,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=10,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_filestat_get(fd=10)
<== (filestat={filetype=REGULAR_FILE,size=5,mtim=1672391667959917172},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=10,iovs=169704,iovs_len=1)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=10,iovs=169704,iovs_len=1)
<== (nread=0,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=10)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestFstat,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=11,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_filestat_get(fd=11)
<== (filestat={filetype=REGULAR_FILE,size=5,mtim=1672391667959917172},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=11)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestFstat)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRemove18446744072748517615)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/TestRemove18446744072748517615)
<== errno=ENOENT
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRemove18446744072748517615,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=12,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=12,iovs=169912,iovs_len=1)
<== (nwritten=3,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=12)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRemove18446744072748517615,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_filestat_get(fd=13)
<== (filestat={filetype=REGULAR_FILE,size=3,mtim=1672391667961180941},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=13,iovs=169784,iovs_len=1)
<== (nread=3,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=13,iovs=169784,iovs_len=1)
<== (nread=0,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=13)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRemove18446744072748517615)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRename-from,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=14,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=14)
<== errno=ESUCCESS
--> wasi_snapshot_preview1.path_rename(fd=3,old_path=tmp/TestRename-from,new_fd=3,new_path=tmp/TestRename-to)
<-- errno=ENOSYS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/TestRename-to)
<== (filestat=,errno=ENOENT)
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRename-to)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/TestRename-to)
<== errno=ENOENT
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRename-from)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRenameOverwrite-to,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=15,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=15,iovs=169864,iovs_len=1)
<== (nwritten=2,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=15)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRenameOverwrite-from,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=16,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=16,iovs=169864,iovs_len=1)
<== (nwritten=4,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=16)
<== errno=ESUCCESS
--> wasi_snapshot_preview1.path_rename(fd=3,old_path=tmp/TestRenameOverwrite-from,new_fd=3,new_path=tmp/TestRenameOverwrite-to)
<-- errno=ENOSYS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/TestRenameOverwrite-from)
<== (filestat={filetype=REGULAR_FILE,size=4,mtim=1672391667962990053},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/TestRenameOverwrite-to)
<== (filestat={filetype=REGULAR_FILE,size=2,mtim=1672391667962849082},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRenameOverwrite-from)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRenameOverwrite-to)
<== errno=ESUCCESS
--> wasi_snapshot_preview1.path_rename(fd=3,old_path=tmp/RenameFailed-from,new_fd=3,new_path=tmp/RenameFailed-to)
<-- errno=ENOSYS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRead0125313401,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=17,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=17,iovs=170040,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=17)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestRead0125313401,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=18,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=18,iovs=170088,iovs_len=1)
<== (nread=0,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=18,iovs=170088,iovs_len=1)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=17)
<== errno=EBADF
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestRead0125313401)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAt078653387,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=19,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=19,iovs=170088,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_pread(fd=19,iovs=170120,iovs_len=1,offset=0)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=19)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestReadAt078653387)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestSeek194998719,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=20,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=20,iovs=169976,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=0,whence=1,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=0,whence=0,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=5,whence=0,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=0,whence=2,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=0,whence=0,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=-1,whence=2,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=8589934592,whence=0,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=8589934592,whence=2,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=4294967295,whence=0,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=0,whence=1,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=8589934591,whence=0,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_seek(fd=20,offset=0,whence=1,result.newoffset=170072)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_close(fd=20)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestSeek194998719)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAt93939429,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=21,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=21,iovs=170072,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_pread(fd=21,iovs=170104,iovs_len=1,offset=7)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=21)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestReadAt93939429)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAtOffset138463557,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=22,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=22,iovs=169944,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=22)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAtOffset138463557,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=23,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_pread(fd=23,iovs=169976,iovs_len=1,offset=7)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_read(fd=23,iovs=169992,iovs_len=1)
<== (nread=5,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=22)
<== errno=EBADF
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestReadAtOffset138463557)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAtNegativeOffset268415679,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=24,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=24,iovs=170056,iovs_len=1)
<== (nwritten=13,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=24)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAtNegativeOffset268415679,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=25,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=24)
<== errno=EBADF
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestReadAtNegativeOffset268415679)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/TestReadAtEOF119095307,oflags=CREAT|EXCL,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=26,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_pread(fd=26,iovs=170184,iovs_len=1,offset=0)
<== (nread=0,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=26)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/TestReadAtEOF119095307)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/./dir2)
<== (filestat=,errno=ENOENT)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/.)
<== (filestat={filetype=DIRECTORY,size=64,mtim=1672360170151273172},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_create_directory(fd=3,path=tmp/_TestMkdirAll_/dir/./dir2)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/./dir2)
<== (filestat={filetype=DIRECTORY,size=64,mtim=1672391667968242568},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/./dir2/file,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=28,errno=ESUCCESS)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/./dir2/file)
<== (filestat={filetype=REGULAR_FILE,size=0,mtim=1672391667968348626},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/./dir2/file/subdir)
<== (filestat=,errno=ENOTDIR)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/_TestMkdirAll_/dir/./dir2/file)
<== (filestat={filetype=REGULAR_FILE,size=0,mtim=1672391667968348626},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=28)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/_TestMkdirAll_/dir/./dir2/file)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/_TestMkdirAll_)
<== errno=EISDIR
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/_TestMkdirAll_)
<== errno=ENOTEMPTY
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/_TestMkdirAll_/dir)
<== errno=EISDIR
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/_TestMkdirAll_/dir)
<== errno=ENOTEMPTY
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/_TestMkdirAll_/dir/dir2)
<== errno=EISDIR
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/_TestMkdirAll_/dir/dir2)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=tmp/dir)
<== errno=EISDIR
==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=tmp/dir)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_create_directory(fd=3,path=tmp/dir)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/dir)
<== (filestat={filetype=DIRECTORY,size=64,mtim=1672391667969817105},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=,path=tmp/dir)
<== (filestat={filetype=DIRECTORY,size=64,mtim=1672391667969817105},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_fdstat_get(fd=3)
<== (stat={filetype=DIRECTORY,fdflags=APPEND,fs_rights_base=,fs_rights_inheriting=},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_open(fd=3,dirflags=SYMLINK_FOLLOW,path=tmp/file,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
<== (opened_fd=30,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=30,iovs=170168,iovs_len=1)
<== (nwritten=7,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_close(fd=30)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=SYMLINK_FOLLOW,path=tmp/file)
<== (filestat={filetype=REGULAR_FILE,size=7,mtim=1672391667970851382},errno=ESUCCESS)
==> wasi_snapshot_preview1.path_filestat_get(fd=3,flags=,path=tmp/file)
<== (filestat={filetype=REGULAR_FILE,size=7,mtim=1672391667970851382},errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=1,iovs=170568,iovs_len=1)
=== RUN   TestExpand
--- PASS: TestExpand (0.00s)
=== RUN   TestConsistentEnviron
--- PASS: TestConsistentEnviron (0.00s)
=== RUN   TestUnsetenv
--- PASS: TestUnsetenv (0.00s)
=== RUN   TestClearenv
--- PASS: TestClearenv (0.00s)
=== RUN   TestLookupEnv
--- PASS: TestLookupEnv (0.00s)
=== RUN   TestEnvironConsistency
--- PASS: TestEnvironConsistency (0.00s)
=== RUN   TestSetenvUnixEinval
--- PASS: TestSetenvUnixEinval (0.00s)
=== RUN   TestExpandEnvShellSpecialVar
--- PASS: TestExpandEnvShellSpecialVar (0.00s)
=== RUN   TestTempDir
--- PASS: TestTempDir (0.00s)
=== RUN   TestChdir
--- PASS: TestChdir (0.00s)
=== RUN   TestStandardFd
--- PASS: TestStandardFd (0.00s)
=== RUN   TestFd
--- PASS: TestFd (0.00s)
=== RUN   TestGetpagesize
--- PASS: TestGetpagesize (0.00s)
=== RUN   TestMkdir
--- PASS: TestMkdir (0.00s)
=== RUN   TestStatBadDir
--- PASS: TestStatBadDir (0.00s)
=== RUN   TestFstat
--- PASS: TestFstat (0.00s)
=== RUN   TestRemove
--- PASS: TestRemove (0.00s)
=== RUN   TestRename
--- FAIL: TestRename (0.00s)
    rename "/tmp/TestRename-to", "/tmp/TestRename-from" failed: rename /tmp/TestRename-from /tmp/TestRename-to: errno 52
    FailNow is incomplete, requires runtime.Goexit()
    stat "/tmp/TestRename-to" failed: stat /tmp/TestRename-to: file does not exist
=== RUN   TestRenameOverwriteDest
--- FAIL: TestRenameOverwriteDest (0.00s)
    rename "/tmp/TestRenameOverwrite-to", "/tmp/TestRenameOverwrite-from" failed: rename /tmp/TestRenameOverwrite-from /tmp/TestRenameOverwrite-to: errno 52
    FailNow is incomplete, requires runtime.Goexit()
    from file "/tmp/TestRenameOverwrite-from" still exists
    "to" size = 2; want 4 (old "from" size)
=== RUN   TestRenameFailed
--- PASS: TestRenameFailed (0.00s)
=== RUN   TestUserHomeDir
--- PASS: TestUserHomeDir (0.00s)
    UserHomeDir failed: $HOME is not defined
=== RUN   TestDirFS
--- PASS: TestDirFS (0.00s)
    TODO: allow foo/bar/. as synonym for path foo/bar on wasi?
=== RUN   TestDirFSPathsValid
--- PASS: TestDirFSPathsValid (0.00s)
    skipping on wasi because it fails on wasi on windows
=== RUN   TestRead0
--- PASS: TestRead0 (0.00s)
=== RUN   TestReadAt0
--- PASS: TestReadAt0 (0.00s)
=== RUN   TestSeek
--- PASS: TestSeek (0.00s)
=== RUN   TestReadAt
--- PASS: TestReadAt (0.00s)
=== RUN   TestReadAtOffset
--- PASS: TestReadAtOffset (0.00s)
=== RUN   TestReadAtNegativeOffset
--- PASS: TestReadAtNegativeOffset (0.00s)
=== RUN   TestReadAtEOF
--- PASS: TestReadAtEOF (0.00s)
=== RUN   TestMkdirAll
--- PASS: TestMkdirAll (0.00s)
=== RUN   TestDirAndSymlinkStats
--- PASS: TestDirAndSymlinkStats (0.00s)
=== RUN   TestFileAndSymlinkStats
--- PASS: TestFileAndSymlinkStats (0.00s)
<== (nwritten=2675,errno=ESUCCESS)
==> wasi_snapshot_preview1.fd_write(fd=1,iovs=170808,iovs_len=1)
FAIL
<== (nwritten=5,errno=ESUCCESS)
```

codefromthecrypt: Here is the output without the detailed logging. The only thing left to pass os package tests in tinygo is to implement rename. This isn't to say we aren't missing features, but in any case it is a milestone for sure.

```bash
$ wazero run  -mount=.:/ os.wasm -test.v
=== RUN   TestExpand
--- PASS: TestExpand (0.00s)
=== RUN   TestConsistentEnviron
--- PASS: TestConsistentEnviron (0.00s)
=== RUN   TestUnsetenv
--- PASS: TestUnsetenv (0.00s)
=== RUN   TestClearenv
--- PASS: TestClearenv (0.00s)
=== RUN   TestLookupEnv
--- PASS: TestLookupEnv (0.00s)
=== RUN   TestEnvironConsistency
--- PASS: TestEnvironConsistency (0.00s)
=== RUN   TestSetenvUnixEinval
--- PASS: TestSetenvUnixEinval (0.00s)
=== RUN   TestExpandEnvShellSpecialVar
--- PASS: TestExpandEnvShellSpecialVar (0.00s)
=== RUN   TestTempDir
--- PASS: TestTempDir (0.00s)
=== RUN   TestChdir
--- PASS: TestChdir (0.00s)
=== RUN   TestStandardFd
--- PASS: TestStandardFd (0.00s)
=== RUN   TestFd
--- PASS: TestFd (0.00s)
=== RUN   TestGetpagesize
--- PASS: TestGetpagesize (0.00s)
=== RUN   TestMkdir
--- PASS: TestMkdir (0.00s)
=== RUN   TestStatBadDir
--- PASS: TestStatBadDir (0.00s)
=== RUN   TestFstat
--- PASS: TestFstat (0.00s)
=== RUN   TestRemove
--- PASS: TestRemove (0.00s)
=== RUN   TestRename
--- FAIL: TestRename (0.00s)
    rename "/tmp/TestRename-to", "/tmp/TestRename-from" failed: rename /tmp/TestRename-from /tmp/TestRename-to: errno 52
    FailNow is incomplete, requires runtime.Goexit()
    stat "/tmp/TestRename-to" failed: stat /tmp/TestRename-to: file does not exist
=== RUN   TestRenameOverwriteDest
--- FAIL: TestRenameOverwriteDest (0.00s)
    rename "/tmp/TestRenameOverwrite-to", "/tmp/TestRenameOverwrite-from" failed: rename /tmp/TestRenameOverwrite-from /tmp/TestRenameOverwrite-to: errno 52
    FailNow is incomplete, requires runtime.Goexit()
    from file "/tmp/TestRenameOverwrite-from" still exists
    "to" size = 2; want 4 (old "from" size)
=== RUN   TestRenameFailed
--- PASS: TestRenameFailed (0.00s)
=== RUN   TestUserHomeDir
--- PASS: TestUserHomeDir (0.00s)
    UserHomeDir failed: $HOME is not defined
=== RUN   TestDirFS
--- PASS: TestDirFS (0.00s)
    TODO: allow foo/bar/. as synonym for path foo/bar on wasi?
=== RUN   TestDirFSPathsValid
--- PASS: TestDirFSPathsValid (0.00s)
    skipping on wasi because it fails on wasi on windows
=== RUN   TestRead0
--- PASS: TestRead0 (0.00s)
=== RUN   TestReadAt0
--- PASS: TestReadAt0 (0.00s)
=== RUN   TestSeek
--- PASS: TestSeek (0.00s)
=== RUN   TestReadAt
--- PASS: TestReadAt (0.00s)
=== RUN   TestReadAtOffset
--- PASS: TestReadAtOffset (0.00s)
=== RUN   TestReadAtNegativeOffset
--- PASS: TestReadAtNegativeOffset (0.00s)
=== RUN   TestReadAtEOF
--- PASS: TestReadAtEOF (0.00s)
=== RUN   TestMkdirAll
--- PASS: TestMkdirAll (0.00s)
=== RUN   TestDirAndSymlinkStats
--- PASS: TestDirAndSymlinkStats (0.00s)
=== RUN   TestFileAndSymlinkStats
--- PASS: TestFileAndSymlinkStats (0.00s)
FAIL
```

Patch:
diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go
index c2579074..c1e5c2f4 100644
--- a/imports/wasi_snapshot_preview1/fs.go
+++ b/imports/wasi_snapshot_preview1/fs.go
@@ -1293,16 +1293,13 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) Errno {
 
 	dirfd := uint32(params[0])
 
-	// TODO: dirflags is a lookupflags and it only has one bit: symlink_follow
+	// TODO: dirflags is a lookupflags, and it only has one bit: symlink_follow
 	// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags
 	_ /* dirflags */ = uint32(params[1])
 
 	path := uint32(params[2])
 	pathLen := uint32(params[3])
 
-	// oflags are currently not something we can pass to the filesystem to
-	// enforce, because fs.FS has no flags parameter. So, we have to validate
-	// them externally, in worst case after the file was already allocated.
 	oflags := uint16(params[4])
 
 	// rights aren't used
@@ -1321,7 +1318,7 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	var newFD uint32
 	var err error
 	if isDir && oflags&O_CREAT != 0 {
-		newFD, err = fsc.Mkdir(pathName, 0o700)
+		return ErrnoInval // use pathCreateDirectory!
 	} else {
 		newFD, err = fsc.OpenFile(pathName, fileOpenFlags, 0o600)
 	}
@@ -1370,12 +1367,15 @@ func atPath(fsc *sys.FSContext, mem api.Memory, dirfd, path, pathLen uint32) (st
 
 func openFlags(oflags, fdflags uint16) (openFlags int, isDir bool) {
 	isDir = oflags&O_DIRECTORY != 0
-	openFlags = os.O_RDONLY
-	if oflags&O_CREAT != 0 {
-		if !isDir { // assume read write
-			openFlags = os.O_RDWR
-		}
-		openFlags |= os.O_CREATE
+	switch {
+	case oflags&O_TRUNC != 0:
+		openFlags = os.O_RDWR | os.O_TRUNC
+	case oflags&O_CREAT != 0:
+		openFlags = os.O_RDWR | os.O_CREATE
+	case fdflags&FD_APPEND != 0:
+		openFlags = os.O_RDWR | os.O_APPEND
+	default:
+		openFlags = os.O_RDONLY
 	}
 	if isDir {
 		return
@@ -1383,12 +1383,6 @@ func openFlags(oflags, fdflags uint16) (openFlags int, isDir bool) {
 	if oflags&O_EXCL != 0 {
 		openFlags |= os.O_EXCL
 	}
-	if oflags&O_TRUNC != 0 {
-		openFlags |= os.O_TRUNC
-	}
-	if fdflags&FD_APPEND != 0 {
-		openFlags |= os.O_APPEND
-	}
 	return
 }
 
diff --git a/internal/sys/fs.go b/internal/sys/fs.go
index 6663e751..34997e65 100644
--- a/internal/sys/fs.go
+++ b/internal/sys/fs.go
@@ -317,15 +317,23 @@ func (c *FSContext) Mkdir(name string, perm fs.FileMode) (newFD uint32, err erro
 
 // OpenFile is like syscall.Open and returns the file descriptor of the new file or an error.
 func (c *FSContext) OpenFile(name string, flags int, perm fs.FileMode) (newFD uint32, err error) {
-	create := flags&os.O_CREATE != 0
 	var f fs.File
 	if wfs, ok := c.fs.(syscallfs.FS); ok {
 		name = c.cleanPath(name)
 		f, err = wfs.OpenFile(name, flags, perm)
-	} else if create {
-		err = syscall.ENOSYS
 	} else {
-		f, err = c.openFile(name)
+		// While os.Open says it is read-only, in reality the files returned
+		// are often writable. Fail only on the flags which won't work.
+		switch {
+		case flags&os.O_APPEND != 0:
+			fallthrough
+		case flags&os.O_CREATE != 0:
+			fallthrough
+		case flags&os.O_TRUNC != 0:
+			return 0, syscall.ENOSYS
+		default:
+			f, err = c.openFile(name)
+		}
 	}
 
 	if err != nil {


Test patch:
diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go
index b8c55b23..0b8a4e60 100644
--- a/imports/wasi_snapshot_preview1/fs_test.go
+++ b/imports/wasi_snapshot_preview1/fs_test.go
@@ -2237,51 +2237,259 @@ func Test_pathLink(t *testing.T) {
 }
 
 func Test_pathOpen(t *testing.T) {
-	expectedFD := sys.FdRoot + 1
-	// set up the initial memory to include the path name starting at an offset.
-	pathName := "wazero"
-	initialMemory := append([]byte{'?'}, pathName...)
+	osDir := t.TempDir()      // open before loop to ensure no locking problems.
+	writefsDir := t.TempDir() // open before loop to ensure no locking problems.
+	os := os.DirFS(osDir)
+	writeFS := writefs.DirFS(writefsDir)
 
-	expectedMemory := append(
-		initialMemory,
-		'?', // `resultOpenedFd` is after this
-		byte(expectedFD), 0, 0, 0,
-		'?',
-	)
+	fileName := "file"
+	fileContents := []byte("012")
+	writeFile(t, osDir, fileName, fileContents)
+	writeFile(t, writefsDir, fileName, fileContents)
 
-	dirflags := uint32(0)
-	path := uint32(1)
-	pathLen := uint32(len(pathName))
-	oflags := uint32(0)
-	fsRightsBase := uint64(1)       // ignored: rights were removed from WASI.
-	fsRightsInheriting := uint64(2) // ignored: rights were removed from WASI.
-	fdflags := uint32(0)
-	resultOpenedFd := uint32(len(initialMemory) + 1)
+	appendName := "append"
+	appendContents := []byte("345")
+	writeFile(t, osDir, appendName, appendContents)
+	writeFile(t, writefsDir, appendName, appendContents)
 
-	testFS := fstest.MapFS{pathName: &fstest.MapFile{Mode: os.ModeDir}}
-	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFS(testFS))
-	defer r.Close(testCtx)
+	truncName := "trunc"
+	truncContents := []byte("678")
+	writeFile(t, osDir, truncName, truncContents)
+	writeFile(t, writefsDir, truncName, truncContents)
 
-	maskMemory(t, mod, len(expectedMemory))
-	ok := mod.Memory().Write(0, initialMemory)
-	require.True(t, ok)
+	dirName := "dir"
+	mkdir(t, osDir, dirName)
+	mkdir(t, writefsDir, dirName)
 
-	requireErrno(t, ErrnoSuccess, mod, PathOpenName, uint64(sys.FdRoot), uint64(dirflags), uint64(path),
-		uint64(pathLen), uint64(oflags), fsRightsBase, fsRightsInheriting, uint64(fdflags), uint64(resultOpenedFd))
-	require.Equal(t, `
-==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=wazero,oflags=,fs_rights_base=FD_DATASYNC,fs_rights_inheriting=FD_READ,fdflags=)
+	dirFileName := path.Join(dirName, fileName)
+	dirFileContents := []byte("def")
+	writeFile(t, osDir, dirFileName, dirFileContents)
+	writeFile(t, writefsDir, dirFileName, dirFileContents)
+
+	expectedOpenedFd := sys.FdRoot + 1
+
+	tests := []struct {
+		name          string
+		fs            fs.FS
+		path          func(t *testing.T) string
+		oflags        uint16
+		fdflags       uint16
+		expected      func(t *testing.T, fsc *sys.FSContext)
+		expectedErrno Errno
+		expectedLog   string
+	}{
+		{
+			name: "os.DirFS",
+			fs:   os,
+			path: func(*testing.T) string { return fileName },
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				requireContents(t, fsc, expectedOpenedFd, fileName, fileContents)
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=file,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
 <== (opened_fd=4,errno=ESUCCESS)
-`, "\n"+log.String())
+`,
+		},
+		{
+			name: "writefs.DirFS",
+			fs:   writeFS,
+			path: func(*testing.T) string { return fileName },
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				requireContents(t, fsc, expectedOpenedFd, fileName, fileContents)
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=file,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=4,errno=ESUCCESS)
+`,
+		},
+		{
+			name:          "os.DirFS FD_APPEND",
+			fs:            os,
+			fdflags:       FD_APPEND,
+			path:          func(t *testing.T) (file string) { return appendName },
+			expectedErrno: ErrnoNosys,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=append,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=APPEND)
+<== (opened_fd=,errno=ENOSYS)
+`,
+		},
+		{
+			name:    "writefs.DirFS FD_APPEND",
+			fs:      writeFS,
+			path:    func(t *testing.T) (file string) { return appendName },
+			fdflags: FD_APPEND,
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				contents := []byte("hello")
+				_, err := fsc.FdWriter(expectedOpenedFd).Write(contents)
+				require.NoError(t, err)
+				require.True(t, fsc.CloseFile(expectedOpenedFd))
 
-	actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
-	require.True(t, ok)
-	require.Equal(t, expectedMemory, actual)
+				// verify the contents were appended
+				b := readFile(t, writefsDir, appendName)
+				require.Equal(t, append(appendContents, contents...), b)
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=append,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=APPEND)
+<== (opened_fd=4,errno=ESUCCESS)
+`,
+		},
+		{
+			name:          "os.DirFS O_CREAT",
+			fs:            os,
+			oflags:        O_CREAT,
+			expectedErrno: ErrnoNosys,
+			path:          func(*testing.T) string { return "creat" },
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=creat,oflags=CREAT,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=,errno=ENOSYS)
+`,
+		},
+		{
+			name:   "writefs.DirFS O_CREAT",
+			fs:     writeFS,
+			path:   func(t *testing.T) (file string) { return "creat" },
+			oflags: O_CREAT,
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				// expect to create a new file
+				contents := []byte("hello")
+				_, err := fsc.FdWriter(expectedOpenedFd).Write(contents)
+				require.NoError(t, err)
+				require.True(t, fsc.CloseFile(expectedOpenedFd))
 
+				// verify the contents were written
+				b := readFile(t, writefsDir, "creat")
+				require.Equal(t, contents, b)
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=creat,oflags=CREAT,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=4,errno=ESUCCESS)
+`,
+		},
+		{
+			name:   "os.DirFS O_DIRECTORY",
+			fs:     os,
+			oflags: O_DIRECTORY,
+			path:   func(*testing.T) string { return dirName },
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				stat, err := fsc.StatFile(expectedOpenedFd)
+				require.NoError(t, err)
+				require.True(t, stat.IsDir())
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=dir,oflags=DIRECTORY,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=4,errno=ESUCCESS)
+`,
+		},
+		{
+			name:   "writefs.DirFS O_DIRECTORY",
+			fs:     writeFS,
+			path:   func(*testing.T) string { return dirName },
+			oflags: O_DIRECTORY,
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				stat, err := fsc.StatFile(expectedOpenedFd)
+				require.NoError(t, err)
+				require.True(t, stat.IsDir())
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=dir,oflags=DIRECTORY,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=4,errno=ESUCCESS)
+`,
+		},
+		{
+			name:          "os.DirFS O_TRUNC",
+			fs:            os,
+			oflags:        O_TRUNC,
+			expectedErrno: ErrnoNosys,
+			path:          func(*testing.T) string { return "trunc" },
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=trunc,oflags=TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=,errno=ENOSYS)
+`,
+		},
+		{
+			name:   "writefs.DirFS O_TRUNC",
+			fs:     writeFS,
+			path:   func(t *testing.T) (file string) { return "trunc" },
+			oflags: O_TRUNC,
+			expected: func(t *testing.T, fsc *sys.FSContext) {
+				contents := []byte("hello")
+				_, err := fsc.FdWriter(expectedOpenedFd).Write(contents)
+				require.NoError(t, err)
+				require.True(t, fsc.CloseFile(expectedOpenedFd))
+
+				// verify the contents were truncated
+				b := readFile(t, writefsDir, "trunc")
+				require.Equal(t, contents, b)
+			},
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=trunc,oflags=TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=4,errno=ESUCCESS)
+`,
+		},
+	}
+
+	for _, tt := range tests {
+		tc := tt
+
+		t.Run(tc.name, func(t *testing.T) {
+			mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFS(tc.fs))
+			defer r.Close(testCtx)
+			pathName := tc.path(t)
+			mod.Memory().Write(0, []byte(pathName))
+
+			path := uint32(0)
+			pathLen := uint32(len(pathName))
+			resultOpenedFd := pathLen
+			dirfd := sys.FdRoot
+
+			// TODO: dirflags is a lookupflags and it only has one bit: symlink_follow
+			// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags
+			dirflags := 0
+
+			// rights aren't used
+			fsRightsBase, fsRightsInheriting := uint64(0), uint64(0)
+
+			requireErrno(t, tc.expectedErrno, mod, PathOpenName, uint64(dirfd), uint64(dirflags), uint64(path),
+				uint64(pathLen), uint64(tc.oflags), fsRightsBase, fsRightsInheriting, uint64(tc.fdflags), uint64(resultOpenedFd))
+			require.Equal(t, tc.expectedLog, "\n"+log.String())
+
+			if tc.expectedErrno == ErrnoSuccess {
+				openedFd, ok := mod.Memory().ReadUint32Le(pathLen)
+				require.True(t, ok)
+				require.Equal(t, expectedOpenedFd, openedFd)
+
+				tc.expected(t, mod.(*wasm.CallContext).Sys.FS())
+			}
+		})
+	}
+}
+
+func requireContents(t *testing.T, fsc *sys.FSContext, expectedOpenedFd uint32, fileName string, fileContents []byte) {
 	// verify the file was actually opened
-	fsc := mod.(*wasm.CallContext).Sys.FS()
-	f, ok := fsc.OpenedFile(expectedFD)
+	f, ok := fsc.OpenedFile(expectedOpenedFd)
 	require.True(t, ok)
-	require.Equal(t, pathName, f.Name)
+	require.Equal(t, fileName, f.Name)
+
+	// verify the contents are readable
+	b, err := io.ReadAll(fsc.FdReader(expectedOpenedFd))
+	require.NoError(t, err)
+	require.Equal(t, fileContents, b)
+}
+
+func mkdir(t *testing.T, tmpDir, dir string) {
+	err := os.Mkdir(path.Join(tmpDir, dir), 0o700)
+	require.NoError(t, err)
+}
+
+func readFile(t *testing.T, tmpDir, file string) []byte {
+	contents, err := os.ReadFile(path.Join(tmpDir, file))
+	require.NoError(t, err)
+	return contents
+}
+
+func writeFile(t *testing.T, tmpDir, file string, contents []byte) {
+	err := os.WriteFile(path.Join(tmpDir, file), contents, 0o600)
+	require.NoError(t, err)
 }
 
 func Test_pathOpen_Errors(t *testing.T) {
@@ -2373,7 +2581,7 @@ func Test_pathOpen_Errors(t *testing.T) {
 `,
 		},
 		{
-			name:          "oflags=directory, but not a directory",
+			name:          "O_DIRECTORY, but not a directory",
 			oflags:        uint32(O_DIRECTORY),
 			fd:            validFD,
 			pathName:      fileName,
@@ -2383,6 +2591,19 @@ func Test_pathOpen_Errors(t *testing.T) {
 			expectedLog: `
 ==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=notdir,oflags=DIRECTORY,fs_rights_base=,fs_rights_inheriting=,fdflags=)
 <== (opened_fd=,errno=ENOTDIR)
+`,
+		},
+		{
+			name:          "oflags=directory and create invalid",
+			oflags:        uint32(O_DIRECTORY | O_CREAT),
+			fd:            validFD,
+			pathName:      fileName,
+			path:          validPath,
+			pathLen:       validPathLen,
+			expectedErrno: ErrnoInval,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=notdir,oflags=CREAT|DIRECTORY,fs_rights_base=,fs_rights_inheriting=,fdflags=)
+<== (opened_fd=,errno=EINVAL)
 `,
 		},
 	}