Closed
Description
Here's an example:
use std::io::{println, File, Open, Truncate, Write, ReadWrite, BufferedStream};
fn main() {
let path = Path::new("test");
let mut file = File::open_mode(&path, Truncate, Write).unwrap();
file.write_str("123456789").unwrap();
drop(file);
let file = File::open_mode(&path, Open, ReadWrite).unwrap();
let mut bs = BufferedStream::new(file);
println(bs.read_exact(2).unwrap().into_ascii().into_string().as_slice());
bs.write_str("xyz").unwrap();
bs.flush().unwrap();
println(bs.read_to_string().unwrap().as_slice());
}
This prints
12
3456789
and afterwards the file contains the string 123456789xyz
even though logically the write happens between the two reads and should have moved the file position over the 345
without them being returned from read calls instead of appending to the end (or overwriting the wrong bytes if a tiny buffer size is chosen). This makes the buffering leak through the abstraction where a mostly equivalent C program maintains the illusion:
#include <stdio.h>
int main(void) {
char buf[10] = { 0 };
FILE* f;
f = fopen("test", "w");
fwrite("123456789", 1, 9, f);
fclose(f);
f = fopen("test", "r+");
fread(buf, 1, 2, f);
puts(buf);
fwrite("xyz", 1, 3, f);
fread(buf, 1, 9, f);
puts(buf);
fclose(f);
return 0;
}
printing
12
6789
and leaving the file to contain 12xyz6789
. strace suggests glibc just seems to seek backwards (lseek(3, -7, SEEK_CUR)
) before the write presumably for the length of the discarded read buffer or otherwise manually keeping track of the logical file position.