Safe way to write file to disk?

I want to write program that save several megabytes to disk and report to user that "all ok, your data is safe".
So if after my program report that all ok powerloss happens or something like this, data in file should not be lost or damanged with high probability.

As I know on Linux you most probably get this done by using:

open(tempname), write(tmpfile), fsync(tmpfile), close(tmpfile), fsync(dir), rename(), fsync(dir)

as described https://lwn.net/Articles/457667/ ,

is any crate to make it in cross platfrom way, at least for Mac/Linux/Windows?

By the way, as know sqlite do it in right way, but sqlite for my task is overkill.

1 Like

You will want to do some reading on the std::fs module for file operations. You can perform your normal file operations there, and anything in that module is cross-platform.
To abstract over some of the byte-level operations, you probably want to look at the std::io module. It contains several good options for making reading and writing to streams of any type (including from files) more ergonomic.

The tempfile crate supports the temp-then-rename pattern well.

2 Likes

The tempfile crate supports
the temp-then-rename pattern well.

I’m currently researching what options there are in Rust to
address the same issue @davemilter has. AFAICS the tempfile
crate does not fully implement the atomic rename idiom
considering how [the calls to fsync(2) are missing]
(https://github.com/Stebalien/tempfile/blob/master/src/file/imp/unix.rs#L107).
Unless you are using a filesystem with stronger-than-usual
guarantees on rename(2)
,
it is generally a bad idea to assume rename(2) had any effect
in the file system before the second sync operation completes. [0]

FWIW I’ve opened an issue on GH asking for clarification whether
this is intentional.

[0] The second fsync() call is actually the only necessary
operation that is unavailable in std. For files there is
.sync_all() but no analogue seems to exist for directory
handles.

As I know on Linux you most probably get this done by using:

open(tempname), write(tmpfile), fsync(tmpfile), close(tmpfile), fsync(dir), rename(), fsync(dir)

as described https://lwn.net/Articles/457667/ ,

is any crate to make it in cross platfrom way, at least for Mac/Linux/Windows?

The rust-atomicwrites crate
seems to be the best option right now.

2 Likes