The POSIX specification defers most semantics of rename to ISO C. It does mention atomicity, but only in the non-normative “Rationale” section, and also again only with reference to ISO C, so this is an aspirational rather than a strict requirement of POSIX. On referral, however, it turns out that the C standard omits an explicit requirement for rename to be atomic. Consequently, rename is not definitively atomic in either POSIX or C.
I’m reminded that NFS was for a long time a popular storage for ISP mail but notoriously prone to non-atomic renames (or anything else, for that matter), and that is why many maildir implementations instead prefer an hard link followed by an unlink, via a tmp/ subdirectory on the same filesystem, during delivery and move/copy operations.
The faulty renames can be handled by looking for stale files and restoring or removing them. Once mail gets into the delivered directory, any duplicate link in a temporary directory gets deleted
They can, but it’s easier to immediately observe the outcome of link(2). What’s more, retrying the hard link is idempotent, whilst retrying a rename is not, especially in distributed or eventually-consistent circumstances. The link/unlink dance sidesteps a whole class of uncertainties. Assuming the filesystem at hand actually supports it, or course.
Right; so if you aren't sure about the filesystem, rename is the simplest most portable thing, plus the dumb workarounds. In practice I've never actually seen the race condition mentioned, but I'm sure it happens on large enough scales.
This is not a race condition. Any filesystem syscall can fail, and not always spectacularly. I can't recommend using rename for moving files into place, except as a fallback for filesystems where hard links are unavailable.
I’m reminded that NFS was for a long time a popular storage for ISP mail but notoriously prone to non-atomic renames (or anything else, for that matter), and that is why many maildir implementations instead prefer an hard link followed by an unlink, via a tmp/ subdirectory on the same filesystem, during delivery and move/copy operations.