C 跨平台 renameat2() rename-if-not-exists 功能

标签 c rename system-calls

是否有一种非特定于平台的方法来执行原子操作“如果 File2 不存在,则将 File1 重命名为 File2,否则给出错误”?我知道我可以检查 File2 是否存在,如果不存在则重命名该文件,但是当其他进程在检查和 rename() 之间创建 File2 时,这会引入潜在的竞争条件。

在 Linux 下,有一个 renameat2() 函数,它通过设置 RENAME_NOREPLACE 标志来完成此操作。不幸的是,联机帮助页上写着

renameat2() is Linux-specific.

我什至不知道是否所有 libc 实现都支持此调用,还是仅 glibc。

对于我的用例,在同一目录内重命名就足够了,我不需要支持移动到完全不同的路径。

这可能与https://stackoverflow.com/a/230581/5562035相关和 Atomically swap contents of two files on Linux

最佳答案

Is there a non-platform-specific way of doing an atomic "rename File1 to File2 if File2 does not exist, otherwise give an error"?

C标准库仅提供rename()用于更改文件名,标准对该函数是这样说的:“如果在调用 rename 函数之前存在由 new 指向的字符串命名的文件,该行为是实现定义的。”因此,如果“非平台特定”被解释为“由 C 标准指定”,那么不,不存在这样的机制。

但是,如果我们扩展“非特定于平台”的范围以允许 POSIX 指定的设施,那么您可以依赖 link() ,其中

shall atomically create a new link for the existing file and the link count of the file shall be incremented by one. [and] shall fail if [... the second argument] resolves to an existing directory entry or refers to a symbolic link.

因此,您可以首先创建到该文件的新(硬)链接,如果指定的路径名​​指定现有文件或符号链接(symbolic link),则失败,然后在成功后删除原始链接。

您可能感兴趣的最著名的非 POSIX 平台是 Windows。我不确定是否有任何方法可以在 Windows 上完成您所要求的操作,但如果有,您可以考虑编写一个包装函数,该函数使用条件编译来选择 POSIX 或 Windows 实现。

关于C 跨平台 renameat2() rename-if-not-exists 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41536199/

相关文章:

C - 将字符串拆分为字符串数组

c - Xmega 只有两个 IO 端口中断(INT0 和 INT1)

svn - 使用 'svn mv' 在 bash 中将目录中的每个文件大写

linux - sigreturn 如何在 SECCOMP_SET_MODE_STRICT 中阻止除 SIGKILL 和 SIGSTOP 之外的所有信号?

c - Linux,使用Socket和读写功能,数据可以分片吗?

c - 在C中以递归方式插入并显示BST

c - pthread(段错误)

linux - 如何使用 cut 命令移动前缀

windows - 使用 Powershell 使用查找文件递归重命名目录

c - inb() 和 outb() Linux 系统调用的包装器