I have this innocent piece of code:
namespace fs = boost::filesystem; auto path = getFilename(); // returns a string fs::create_directories(fs::path(path).parent_path()); std::ofstream ofs(path + "~"); ofs << info; ofs.close(); fs::rename(path + "~", path);
which causes the exception:
boost::filesystem::rename: No such file or directory: "../9f/061b4f7a5e529c964659226eedd4e5~", "../9f/061b4f7a5e529c964659226eedd4e5"
However, I have no idea how that could happen. I use the rename, so that a reading process never sees an empty file, but only no file or filed with info. Is there any race involved between ofs.close() and fs:rename()? The code was executed on a distributed network filesystem (lustre).
Any ideas anyone?
Your code is racy. POSIX offers no guarantee that a file entry continues to exist after an open(). At any moment the file entry may be renamed, deleted, or otherwise disappear or mutate. Your filing system is therefore entirely within specification if the file entry is not there after an open() returns. You should adjust your code to be correct. (To write correct code, you may wish to look into renameat(). You would create an anonymous inode using O_TMPFILE, write its contents, open a handle to the destination directory using O_PATH, and renameat() your temporary inode over the destination file entry, atomically replacing it. If this sounds involved, the P1031 Low level file i/o reference implementation library LLFIO lets you do this portably using a somewhat less low level interface) Niall