Repository: wasmerio/wasmer (language: rust)

Issue:
Opening a file with append should not change existing fd offset
### Describe the bug

If file has been opened with a descriptor `fd0`, opening the same file with the append flag&mdash;producing `fd1`&mdash;should not change the offset of `fd0`.  `fd0` and `fd1` should have independent offsets.

This behavior is consistent across Linux and other Wasm runtimes (Wasmtime, WAMR, WasmEdge, Wazero), but Wasmer changes the offset of the original descriptor.

```sh
wasmer -vV; rustc -vV
wasmer 4.4.0 (8b97cfe 2024-10-18)
binary: wasmer-cli
commit-hash: 8b97cfe3992ae3c2f0002f9955fcb23057f666a9
commit-date: 2024-10-18
host: x86_64-unknown-linux-gnu
compiler: singlepass,cranelift
c_api backend: 
rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7
```


### Steps to reproduce

Compile and run this snippet, mounting some diretory:

```
cargo build --target wasm32-wasip1
wasmer run --mapdir /dir:dir target/wasm32-wasip1/debug/repro.wasm
```

```rust
use std::{
    fs,
    io::{Seek, SeekFrom, Write},
};

fn main() {
    let mut f0 = fs::OpenOptions::new()
        .create(true)
        .write(true)
        .open("file")
        .unwrap();

    f0.write_all(b"abc").unwrap();
    f0.seek(SeekFrom::Start(1)).unwrap();

    assert_eq!(fs::read_to_string("file").unwrap(), "abc");

    // This open with append should not affect the offset of f0.
    let _f1 = fs::OpenOptions::new()
        .create(true)
        .write(true)
        .append(true)
        .open("file")
        .unwrap();

    f0.write_all(b"d").unwrap();

    assert_eq!(fs::read_to_string("file").unwrap(), "adc");
}
```

### Expected behavior

Running this snippet should not panic.

### Actual behavior

Wasmer panics, producing a file with the content `abcd` instead of `adc`.




Discussion / hints:

Fix patch:
diff --git a/lib/wasix/src/syscalls/wasi/fd_write.rs b/lib/wasix/src/syscalls/wasi/fd_write.rs
index 04954d6770e..7793b72a550 100644
--- a/lib/wasix/src/syscalls/wasi/fd_write.rs
+++ b/lib/wasix/src/syscalls/wasi/fd_write.rs
@@ -163,7 +163,7 @@ pub(crate) fn fd_write_internal<M: MemorySize>(
                                 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();
+                                        offset = fd_entry.inode.stat.read().unwrap().st_size;
                                         fd_entry.offset.store(offset, Ordering::Release);
                                     }
 
diff --git a/lib/wasix/src/syscalls/wasi/path_open.rs b/lib/wasix/src/syscalls/wasi/path_open.rs
index 9c8d3c81655..4f8c00d57dd 100644
--- a/lib/wasix/src/syscalls/wasi/path_open.rs
+++ b/lib/wasix/src/syscalls/wasi/path_open.rs
@@ -237,7 +237,7 @@ pub(crate) fn path_open_internal(
                 let open_options = open_options
                     .write(minimum_rights.write)
                     .create(minimum_rights.create)
-                    .append(minimum_rights.append)
+                    .append(false)
                     .truncate(minimum_rights.truncate);
 
                 if minimum_rights.read {


Test patch:
diff --git a/tests/wasi-fyi/fs_open_append_offset.rs b/tests/wasi-fyi/fs_open_append_offset.rs
new file mode 100644
index 00000000000..fef83616f53
--- /dev/null
+++ b/tests/wasi-fyi/fs_open_append_offset.rs
@@ -0,0 +1,31 @@
+use std::{
+    fs,
+    io::{Seek, SeekFrom, Write},
+};
+
+fn main() {
+    let file = "fyi/fs_open_append_offset.dir/file";
+    let mut f0 = fs::OpenOptions::new()
+        .create(true)
+        .truncate(true)
+        .write(true)
+        .open(file)
+        .unwrap();
+
+    f0.write_all(b"abc").unwrap();
+    f0.seek(SeekFrom::Start(1)).unwrap();
+
+    assert_eq!(fs::read_to_string(file).unwrap(), "abc");
+
+    // This open with append should not affect the offset of f0.
+    let _f1 = fs::OpenOptions::new()
+        .create(true)
+        .write(true)
+        .append(true)
+        .open(file)
+        .unwrap();
+
+    f0.write_all(b"d").unwrap();
+
+    assert_eq!(fs::read_to_string(file).unwrap(), "adc");
+}
diff --git a/tests/wasi-fyi/test_fs/fyi/fs_open_append_offset.dir/.gitignore b/tests/wasi-fyi/test_fs/fyi/fs_open_append_offset.dir/.gitignore
new file mode 100644
index 00000000000..f73f3093ff8
--- /dev/null
+++ b/tests/wasi-fyi/test_fs/fyi/fs_open_append_offset.dir/.gitignore
@@ -0,0 +1,1 @@
+file