[Haskell-cafe] How to move files?

Viktor Dukhovni ietf-dane at dukhovni.org
Thu Apr 15 16:42:06 UTC 2021


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:sinkFileCautious

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.


More information about the Haskell-Cafe mailing list