Skip to content

Commit

Permalink
Fix fd_fdstat_set_flags resetting offset
Browse files Browse the repository at this point in the history
This commit fixes `fd_fdstat_set_flags` resetting the fd offset due to
it reopening the file every time.  This fix gets the current offset
before reopening and restore the offset with seek.

Signed-off-by: Yage Hu <me@huyage.dev>
  • Loading branch information
yagehu committed Dec 12, 2023
1 parent 99ededc commit 7478b88
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
17 changes: 17 additions & 0 deletions imports/wasi_snapshot_preview1/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand Down
3 changes: 3 additions & 0 deletions internal/sysfs/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 30 additions & 1 deletion internal/sysfs/osfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 7478b88

Please sign in to comment.