mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-22 16:35:33 +00:00
Fix fd with append flag can't seek correctly
This commit fixes an incompatible behavior (with other runtimes, and POSIX) when an fd that was opened with `fdflags::append` cannot seek to the right offset with `fd_seek`. The append flag should not "lock" the offset at the end, as it's possible to seek to another offset and read from it. Signed-off-by: Yage Hu <me@huyage.dev>
This commit is contained in:
@ -62,9 +62,6 @@ pub(crate) fn fd_seek_internal(
|
||||
if !fd_entry.rights.contains(Rights::FD_SEEK) {
|
||||
return Ok(Err(Errno::Access));
|
||||
}
|
||||
if fd_entry.flags.contains(Fdflags::APPEND) {
|
||||
return Ok(Ok(fd_entry.offset.load(Ordering::Acquire)));
|
||||
}
|
||||
|
||||
// TODO: handle case if fd is a dir?
|
||||
let new_offset = match whence {
|
||||
|
@ -127,6 +127,7 @@ pub(crate) fn fd_write_internal<M: MemorySize>(
|
||||
should_update_cursor: bool,
|
||||
should_snapshot: bool,
|
||||
) -> Result<Result<usize, Errno>, WasiError> {
|
||||
let mut offset = offset;
|
||||
let mut env = ctx.data();
|
||||
let state = env.state.clone();
|
||||
|
||||
@ -160,6 +161,12 @@ pub(crate) fn fd_write_internal<M: MemorySize>(
|
||||
async {
|
||||
let mut handle = handle.write().unwrap();
|
||||
if !is_stdio {
|
||||
if fd_entry.flags.contains(Fdflags::APPEND) {
|
||||
// `fdflags::append` means we need to seek to the end before writing.
|
||||
offset = handle.size();
|
||||
fd_entry.offset.store(offset, Ordering::Release);
|
||||
}
|
||||
|
||||
handle
|
||||
.seek(std::io::SeekFrom::Start(offset))
|
||||
.await
|
||||
|
32
tests/wasi-fyi/fd_seek_append.rs
Normal file
32
tests/wasi-fyi/fd_seek_append.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
#[link(wasm_import_module = "wasi_snapshot_preview1")]
|
||||
extern "C" {
|
||||
pub fn fd_seek(fd: i32, offset: i64, whence: i32, filesize: i32) -> i32;
|
||||
}
|
||||
|
||||
const ERRNO_SUCCESS: i32 = 0;
|
||||
const WHENCE_SET: i32 = 0;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let offset = 100u64;
|
||||
let mut new_offset = 0u64;
|
||||
let f = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open("/fyi/fs_seek_append.dir/file")
|
||||
.unwrap();
|
||||
let errno = fd_seek(
|
||||
f.as_raw_fd(),
|
||||
offset as i64,
|
||||
WHENCE_SET,
|
||||
&mut new_offset as *mut u64 as usize as i32,
|
||||
);
|
||||
|
||||
assert_eq!(errno, ERRNO_SUCCESS);
|
||||
assert_eq!(offset, new_offset);
|
||||
}
|
||||
}
|
@ -13,8 +13,9 @@ fn main() {
|
||||
// file offset must be 1 now
|
||||
write!(file, "{}", "a").unwrap();
|
||||
|
||||
// rewind should not work on file in append mode
|
||||
// since the offset must always be at the end of the file
|
||||
// rewind should not work on file in append mode.
|
||||
// It changes the offset, which is immediately set to the end of the file
|
||||
// with a write.
|
||||
let _ = file.rewind();
|
||||
|
||||
// file offset must be 2 now
|
||||
|
0
tests/wasi-fyi/test_fs/fyi/fs_seek_append.dir/file
Normal file
0
tests/wasi-fyi/test_fs/fyi/fs_seek_append.dir/file
Normal file
Reference in New Issue
Block a user