fs: Adds fd_sync (#1026)
Signed-off-by: Nuno Cruces <ncruces@users.noreply.github.com>
This commit is contained in:
@@ -950,7 +950,24 @@ func fdSeekFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
// and metadata of a file to disk.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_syncfd-fd---errno
|
||||
var fdSync = stubFunction(FdSyncName, []api.ValueType{i32}, "fd")
|
||||
var fdSync = newHostFunc(FdSyncName, fdSyncFn, []api.ValueType{i32}, "fd")
|
||||
|
||||
func fdSyncFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
fd := uint32(params[0])
|
||||
|
||||
type syncer interface{ Sync() error }
|
||||
// Check to see if the file descriptor is available
|
||||
if f, ok := fsc.LookupFile(fd); !ok {
|
||||
return ErrnoBadf
|
||||
// fs.FS doesn't declare Sync, but implementations such as os.File implement it.
|
||||
} else if syncer, ok := f.File.(syncer); !ok {
|
||||
return ErrnoBadf
|
||||
} else if err := syncer.Sync(); err != nil {
|
||||
return ErrnoIo
|
||||
}
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// fdTell is the WASI function named FdTellName which returns the current
|
||||
// offset of a file descriptor.
|
||||
|
||||
@@ -1666,13 +1666,48 @@ func Test_fdSeek_Errors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test_fdSync only tests it is stubbed for GrainLang per #271
|
||||
// Test_fdSync only tests that the call succeeds; it's hard to test its effectiveness.
|
||||
func Test_fdSync(t *testing.T) {
|
||||
log := requireErrnoNosys(t, FdSyncName, 0)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.fd_sync(fd=0)
|
||||
<-- errno=ENOSYS
|
||||
`, log)
|
||||
tmpDir := t.TempDir() // open before loop to ensure no locking problems.
|
||||
pathName := "test_path"
|
||||
mod, fd, log, r := requireOpenFile(t, tmpDir, pathName, []byte{}, false)
|
||||
defer r.Close(testCtx)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fd uint32
|
||||
expectedErrno Errno
|
||||
expectedLog string
|
||||
}{
|
||||
{
|
||||
name: "invalid fd",
|
||||
fd: 42, // arbitrary invalid fd
|
||||
expectedErrno: ErrnoBadf,
|
||||
expectedLog: `
|
||||
==> wasi_snapshot_preview1.fd_sync(fd=42)
|
||||
<== errno=EBADF
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "valid fd",
|
||||
fd: fd,
|
||||
expectedErrno: ErrnoSuccess,
|
||||
expectedLog: `
|
||||
==> wasi_snapshot_preview1.fd_sync(fd=4)
|
||||
<== errno=ESUCCESS
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, tc.expectedErrno, mod, FdSyncName, uint64(tc.fd))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test_fdTell only tests it is stubbed for GrainLang per #271
|
||||
|
||||
@@ -97,7 +97,8 @@ func maybeWrapFile(f file) file {
|
||||
return struct {
|
||||
readFile
|
||||
io.Writer
|
||||
}{f, &windowsWriter{f}}
|
||||
syncer
|
||||
}{f, &windowsWriter{f}, f}
|
||||
}
|
||||
|
||||
// windowsWriter translates error codes not mapped properly by Go.
|
||||
|
||||
@@ -142,4 +142,7 @@ type readFile interface {
|
||||
type file interface {
|
||||
readFile
|
||||
io.Writer
|
||||
syncer
|
||||
}
|
||||
|
||||
type syncer interface{ Sync() error }
|
||||
|
||||
Reference in New Issue
Block a user