diff --git a/lib/wasix/src/syscalls/wasi/fd_write.rs b/lib/wasix/src/syscalls/wasi/fd_write.rs index d42fe2c4053..b5f0d648a82 100644 --- a/lib/wasix/src/syscalls/wasi/fd_write.rs +++ b/lib/wasix/src/syscalls/wasi/fd_write.rs @@ -414,7 +414,7 @@ pub(crate) fn fd_write_internal( // reborrow and update the size if !is_stdio { - let offset = if is_file && should_update_cursor { + let curr_offset = if is_file && should_update_cursor { let bytes_written = bytes_written as u64; let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try_ok_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); @@ -433,10 +433,17 @@ pub(crate) fn fd_write_internal( unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) }; if is_file { let mut stat = fd_entry.inode.stat.write().unwrap(); - // If we wrote before the end, the current size is still correct. - // Otherwise, we only got as far as the current cursor. So, the - // max of the two is the correct new size. - stat.st_size = stat.st_size.max(offset); + if should_update_cursor { + // If we wrote before the end, the current size is still correct. + // Otherwise, we only got as far as the current cursor. So, the + // max of the two is the correct new size. + stat.st_size = stat.st_size.max(curr_offset); + } else { + // pwrite does not update the cursor of the file so to calculate the final + // size of the file we compute where the cursor would have been if it was updated, + // and get the max value between it and the current size. + stat.st_size = stat.st_size.max(offset + bytes_written as u64); + } } else { // Cast is valid because we don't support 128 bit systems... fd_entry.inode.stat.write().unwrap().st_size += bytes_written as u64; diff --git a/tests/wasix/pwrite-and-size/main.c b/tests/wasix/pwrite-and-size/main.c new file mode 100644 index 00000000000..d560553d3db --- /dev/null +++ b/tests/wasix/pwrite-and-size/main.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include + +int main() +{ + int fd; + char *data; + struct stat statbuf; + + fd = open("/data/my_file.txt", O_CREAT | O_WRONLY, 0644); + if (fd == -1) + { + goto fail; + } + + data = "ABC"; + + if (pwrite(fd, data, 3, 0) == -1) + { + goto fail; + } + if (fstat(fd, &statbuf) == -1) + { + goto fail; + } + + if (statbuf.st_size != 3) + { + goto fail; + } + + data = "D"; + if (pwrite(fd, data, 1, 1) == -1) + { + goto fail; + } + + if (fstat(fd, &statbuf) == -1) + { + goto fail; + } + if (statbuf.st_size != 3) + { + goto fail; + } + + data = "XYZ"; + if (pwrite(fd, data, 3, 3) == -1) + { + goto fail; + } + if (fstat(fd, &statbuf) == -1) + { + goto fail; + } + if (statbuf.st_size != 6) + { + goto fail; + } + + data = "GHIJKLMJ"; + if (pwrite(fd, data, 10, 1) == -1) + { + goto fail; + } + if (fstat(fd, &statbuf) == -1) + { + goto fail; + } + + if (statbuf.st_size != 11) + { + goto fail; + } + + printf("0"); + + return 0; + +fail: + printf("1"); + + return 1; +} diff --git a/tests/wasix/pwrite-and-size/run.sh b/tests/wasix/pwrite-and-size/run.sh new file mode 100755 index 00000000000..ba9a2d77c2c --- /dev/null +++ b/tests/wasix/pwrite-and-size/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +$WASMER -q run main.wasm --mapdir=/data:. > output + +printf "0" | diff -u output - 1>/dev/null + +rm my_file.txt \ No newline at end of file