Skip to content

Commit

Permalink
fix file size computation after pwrite (#4942)
Browse files Browse the repository at this point in the history
  • Loading branch information
maminrayej authored Jul 19, 2024
2 parents dbcaee4 + 2051488 commit 5e07d5e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 5 deletions.
17 changes: 12 additions & 5 deletions lib/wasix/src/syscalls/wasi/fd_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ pub(crate) fn fd_write_internal<M: MemorySize>(

// 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));
Expand All @@ -433,10 +433,17 @@ pub(crate) fn fd_write_internal<M: MemorySize>(
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;
Expand Down
86 changes: 86 additions & 0 deletions tests/wasix/pwrite-and-size/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

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;
}
7 changes: 7 additions & 0 deletions tests/wasix/pwrite-and-size/run.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 5e07d5e

Please sign in to comment.