I knew I should never have started using c++ io, the whole ‘type safety’ argument is a red herring (does anyone really find that it’s one of their most pressing problems?). Anyhow, I did, and discovered a strange difference between ifstreams and FILE*s and plain old file descriptors: ifstreams cannot read from a device. Can anyone think of a reason why?
const char* path = '/dev/disk3'; char b; // this works FILE* f= fopen(path, 'rb'); int i = fread(&b, 1, 1, f); // returns 1, success! // this does not work ifstream cf(path, ios::binary); cf.read(&b, 1); bool good = cf.good(); // returns false, failure.
The device is unbuffered and must be read from in 512 byte multiples. ifstream does it’s own buffering and strangely decided to read 1023 bytes ahead, which fails with ‘Invalid argument’. Interestingly, this ifstream is implemented on top of a FILE*. However, FILE* left to its own devices was reading ahead using a nicer, rounder number of bytes.
Thanks to dtrace for vital clues. I guess we’ll never know if the folk who thought they knew answer but didn’t want to say were right.