Unfortunately, looking through the standard there is nothing provided by basic_filebuf
or any of the basic_[io]?fstream
class templates to allow you to extract the underlying OS file descriptor (in the way that fileno()
does for C stdio I/O).
Nor is there an open()
method or constructor that takes such a file descriptor as a parameter (which would allow you to open the file using a different mechanism and record the filehandle).
There is basic_ostream::flush()
, however I suspect that this does not in fact call fsync()
-- I expect that, like fflush()
in stdio, it only makes sure that the user-space runtime library buffers are flushed, meaning that the OS could still be buffering the data.
So in short there appears to be no way to do this portably. :(
What to do? My suggestion is to subclass basic_filebuf<C, T>
:
template <typename charT, typename traits = std::char_traits<charT> >
class my_basic_filebuf : public basic_filebuf<charT, traits> {
....
public:
int fileno() { ... }
....
};
typedef my_basic_filebuf<char> my_filebuf;
To use it, you can construct an ofstream
using the default constructor, then assign the new buffer with rdbuf()
:
my_filebuf buf;
buf.open("somefile.txt");
ofstream ofs;
ofs.rdbuf(&buf);
ofs << "Writing to somefile.txt..." << endl;
int fd = static_cast<my_filebuf*>(ofs.rdbuf())->fileno();
Of course you could also derive a new class from basic_ostream
to make the process of opening a file and retrieving its file descriptor more convenient.