File::seek works unexpectedly

When opening file with append flag, I would expect file position to be at the end. But it reports 0. At the same time, when writing to the file, it behaves as expected, and data will append to the end. It feels like File::seek(SeekFrom::Current(0)) is not synchronized with what real offset is?

#[test]
fn append_test() -> Result<()> {
    use std::fs::{File};
    use std::io::SeekFrom;

    let temp_dir = TempDir::new().expect("unable to create temporary working directory");
    let mut file_name = temp_dir.into_path();
    file_name.push("f1.dat");
    let file_name = file_name.as_path();
    let mut f1 = OpenOptions::new().create(true).write(true).open(file_name)?;
    f1.write_all(&mut vec![1,2,3,4])?;
    f1.sync_all()?;
    drop(f1);

    let mut f2 = OpenOptions::new().append(true).open(file_name)?;
    // Why position is 0 here???!
    println!("Position: {}", f2.seek(SeekFrom::Current(0))?);
    f2.write_all(&mut vec![5,6])?;
    f2.sync_all()?;
    drop(f2);

    let mut buf = Vec::new();
    let mut f3 = File::open(file_name)?;
    f3.read_to_end(&mut buf)?;
    println!("Result: {:?}", buf);

    Ok(())
}
running 1 test
Position: 0
Result: [1, 2, 3, 4, 5, 6]
test append_test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 17 filtered out

I think this depends on the OS. On Linux (and POSIX, I assume) opening a file in append mode means that the file offset is set to the end of the file at every write operation:

O_APPEND
       The file is opened in append mode.  Before  each  write(2),  the
       file  offset  is  positioned  at the end of the file, as if with
       lseek(2).  The modification of the file offset and the write op‐
       eration are performed as a single atomic step.

Also, from the OpenOptions documentation:

If a file is opened with both read and append access, beware that after opening, and after every write, the position for reading may be set at the end of the file. (emphasis added)

So, in general, I don't think you can rely on the offset being correct when using append mode. The only thing you know for sure is that writes will be at the end.

2 Likes

Yeah, too much troubles. I'll just use write and will do positioning explicitly with seek.