with_file_atomic ?temp_file ?perm ?fsync ?replace_special file ~f
creates a writer to a temp file, feeds that writer to f
, and when the result of f
becomes determined, atomically moves (using Unix.rename
) the temp file to file
. If file
currently exists and is a regular file (see below regarding replace_special
) it will be replaced, even if it is read-only.
The temp file will be file
(or temp_file
if supplied) suffixed by a unique random sequence of six characters. The temp file will be removed if an exception is raised to the monitor of f
before the result of f
becomes determined. However, if the program exits for some other reason, the temp file may not be cleaned up; so it may be prudent to choose a temp file that can be easily found by cleanup tools.
If fsync
is true
, the temp file will be flushed to disk before it takes the place of the target file, thus guaranteeing that the target file will always be in a sound state, even after a machine crash. Since synchronization is extremely slow, this is not the default. Think carefully about the event of machine crashes and whether you may need this option!
If replace_special
is false
(the default) an existing special file
(block or character device, socket or FIFO) will not be replaced by a regular file, the temporary file is not created and an exception is raised. To explicitly replace an existing special file
, replace_special
must be passed as true
. Note that if file
exists and is a directory, the rename will fail; if file
exists and is a symbolic link, the link will be replaced, not the target (as per Unix.rename
).
We intend for with_file_atomic
to mimic the behavior of the open
system call, so if file
does not exist, we will apply the current umask to perm
(the effective permissions become perm land lnot umask
, see man 2 open
). However, if file
does exist and perm
is specified, we do something different from open
system call: we override the permission with perm
, ignoring the umask. This means that if you create and then immediately overwrite the file with with_file_atomic ~perm
, then the umask will be honored the first time and ignored the second time. If perm
is not specified, then any existing file permissions are preserved.
If f
closes the writer passed to it, with_file_atomic
raises and does not create file
.