/// This option, when true, means that writes will append to a file instead
/// of overwriting previous contents.
/// Note that setting `.write(true).append(true)` has the same effect as
/// setting only `.append(true)`.
But in fact, .write(true).append(true) is not the same to .append(true):
use std::{fs::{File, OpenOptions}, io::Write};
fn main() {
write!(&mut File::create("foo.txt").unwrap(), "bar").unwrap();
// now foo.txt is bar
write!(&mut OpenOptions::new().read(true).write(true).open("foo.txt").unwrap(),"B").unwrap();
// now foo.txt is Bar
write!(&mut OpenOptions::new().append(true).open("foo.txt").unwrap(),"Baz").unwrap();
// now foo.txt is BarBaz
write!(&mut OpenOptions::new().append(true).write(false).read(false).open("foo.txt").unwrap(), "Foo").unwrap();
// now foo.txt is BarBazFoo
}
For std::io::Write macros, with .append, the file is read and write no matter what the exact value the .read and the .write is set. But with .append, the write will start at the end of the file, while read & write started at the beginning.
Maybe we should modify the doc. I opened an PR about that, but my PR seems not correct, either.
Should we describe the behavior exactly? Or should we just delete the wrong informations?
and by that it should be clear to see that if append is set, the value of write does not matter (but read does).
The write of B in your example does overwrite the previous contents (b), it just doesn't truncate the file. Is that what you missed / wasn't communicated well enough?
That's more clear than the quoted documentation. Perhaps it could be more like:
Note that when the append option is true, the write option is ignored; the file will always be opened with write permission in order to allow appending data. (The read option is still honored.)
Are there platforms where this could be false? C/POSIX may have unified everyone on append == write, but I can imagine a theoretical platform where the beginning of the file is kept immutable, and only writes are allowed past the end of the existing file, which would make write meaningful for the before-appending part.
POSIX allows you to do open(path, O_RDONLY|O_APPEND). If I'm reading https://pubs.opengroup.org/onlinepubs/9799919799/functions/open.html correctly, O_APPEND has no visible effect if paired with O_RDONLY, because the effect of O_APPEND is "the file offset shall be set to the end of the file prior to each write", and you can't write to a file you opened read-only. ("Prior to each write" might sound like the seek position would get set to the end of the file if you tried to write to it, even though the write would fail, but this is not the case; on both Linux and NetBSD, the write fails and has no side effects.)
I don't know the exact semantics for any other operating system.