自Linux 3.15以来,新的renameat2
系统调用可以原子交换同一文件系统上的两个路径。然而,甚至还没有glibc包装器,更不用说coreutils访问它的方法了。所以它看起来会像这样:
int dirfd = open(".../base", O_PATH | O_DIRECTORY | O_CLOEXEC);
syscall(SYS_renameat2, dirfd, "alpha", dirfd, "bravo", RENAME_EXCHANGE);
close(dirfd);
system("rm -rf alpha");
当然,你需要做适当的错误处理等等--请参见此代码片段以获取更复杂的renameat2
包装器。
话虽如此 - 其他人提到的符号链接解决方案更加简单和可移植,因此除非bravo
已经存在且你必须原子地更新它,否则使用符号链接。
2020年更新:自glibc 2.28(发布于2018-08-01(Debian Stretch,Fedora 29))以来,该系统调用的glibc包装器已可用。但是,它仍无法通过coreutils访问。
int dirfd = open(".../base", O_PATH | O_DIRECTORY | O_CLOEXEC);
renameat2(dirfd, "alpha", dirfd, "bravo", RENAME_EXCHANGE);
close(dirfd);
system("rm -rf alpha");