
On Thu, Apr 15, 2021 at 12:32:16PM +0800, ☂Josh Chia (謝任中) wrote:
What's the best way to move the file if possible but copy-and-delete if necessary?
The `conduit` package has `sinkFileCautious` that creates a temporary file in the target directory, deletes it if an exception is thrown, but otherwise renames the temp file to the requested name on success. https://hackage.haskell.org/package/conduit-1.3.4.1/docs/Conduit.html#v:sink... There are fancier things one can do on Linux systems with unnamed temporary files created via openat(2), that can be linked into the target directory only when ready via linkat(2), but this is not particularly portable, and not even supported by all Linux filesystems. AFAIK there is not possible to avoid a narrow window during which the temporary file exists under a transient name, because linkat(2) does not provide a way to atomically replace the target if it exists. So the calling sequence is (with appropriate error checks, not shown): fd = openat(dirfd, ...|O_TMPFILE, mode); write(fd, ...); ... write(fd, ...); (void) unlink("file.tmp"); linkat(fd, "", dirfd, "file.tmp", AT_EMPTY_PATH); renameat(dirfd, "file.tmp", dirfd, "file"); -- Viktor.