diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go index c17c6d9d946..6cae4d0d689 100644 --- a/imports/wasi_snapshot_preview1/fs_test.go +++ b/imports/wasi_snapshot_preview1/fs_test.go @@ -597,6 +597,13 @@ func Test_fdFdstatSetFlags(t *testing.T) { `, "\n"+log.String()) // FIXME? flags==0 prints 'flags=' log.Reset() + requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdSeekName, uint64(fd), uint64(0), uint64(0), uint64(1024)) + require.Equal(t, ` +==> wasi_snapshot_preview1.fd_seek(fd=4,offset=0,whence=0) +<== (newoffset=0,errno=ESUCCESS) +`, "\n"+log.String()) + log.Reset() + // Without O_APPEND flag, the data is written at the beginning. writeWazero() requireFileContent("wazero6789" + "wazero") @@ -609,6 +616,16 @@ func Test_fdFdstatSetFlags(t *testing.T) { `, "\n"+log.String()) // FIXME? flags==1 prints 'flags=APPEND' log.Reset() + // Restoring the O_APPEND flag should not reset fd offset. + requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdTellName, uint64(fd), uint64(1024)) + require.Equal(t, ` +==> wasi_snapshot_preview1.fd_tell(fd=4,result.offset=1024) +<== errno=ESUCCESS +`, "\n"+log.String()) + log.Reset() + offset, _ := mod.Memory().Read(1024, 4) + require.Equal(t, offset, []byte{6, 0, 0, 0}) + // with O_APPEND flag, the data is appended to buffer. writeWazero() requireFileContent("wazero6789" + "wazero" + "wazero") diff --git a/internal/sysfs/file_test.go b/internal/sysfs/file_test.go index b27b2bc45fb..44e7eb54c62 100644 --- a/internal/sysfs/file_test.go +++ b/internal/sysfs/file_test.go @@ -147,6 +147,9 @@ func TestFileSetAppend(t *testing.T) { require.EqualErrno(t, 0, f.SetAppend(false)) require.False(t, f.IsAppend()) + _, errno = f.Seek(0, 0) + require.EqualErrno(t, 0, errno) + // without O_APPEND flag, the data writes at offset zero _, errno = f.Write([]byte("wazero")) require.EqualErrno(t, 0, errno) diff --git a/internal/sysfs/osfile.go b/internal/sysfs/osfile.go index cecab8cbb0b..952a0ca9df4 100644 --- a/internal/sysfs/osfile.go +++ b/internal/sysfs/osfile.go @@ -98,9 +98,38 @@ func (f *osFile) reopen() (errno experimentalsys.Errno) { // Clear any create flag, as we are re-opening, not re-creating. f.flag &= ^experimentalsys.O_CREAT + var ( + isDir bool + offset int64 + err error + ) + + isDir, errno = f.IsDir() + if errno != 0 { + return errno + } + + if !isDir { + offset, err = f.file.Seek(0, 1) + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + } + _ = f.close() f.file, errno = OpenFile(f.path, f.flag, f.perm) - return + if errno != 0 { + return errno + } + + if !isDir { + _, err = f.file.Seek(offset, 0) + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + } + + return 0 } // IsNonblock implements the same method as documented on fsapi.File