如果新旧相同,为什么不重命名任何内容?

如果新旧相同,为什么不重命名任何内容?

我的代码正在做类似的事情link(link_target, hardlink_tmp); rename(hardlink_tmp, hardlink);,目的是始终拥有有效的 dentry hardlink。我希望它能够继续运作dentries,并且永远不会落后hardlink_tmp

然而,今天我发现了许多剩余的hardlink_tmp文件。浏览rename(2)发现:

If oldpath and newpath are existing hard links referring to the same file, then rename() does nothing, and returns a success status.

中的措辞略有不同rename(3p)

If the old argument and the new argument resolve to either the same existing directory entry or different directory entries for the same existing file, rename() shall return successfully and perform no other action.

现在我需要进行最后一次unlink(hardlink_tmp);删除可能陈旧的目录项。

为什么这是理想的行为?

答案1

POSIX 规范中也有将两个名称重命名为同一文件的限制。它在“理由”部分说:

如果旧的和新的引用同一文件的规范旨在保证:

rename("x", "x");

不删除该文件。

这有点简单,但考虑到基本原理也提到了+rename()的替代方案,我想到了 link()unlink()——我纯粹是在猜测——一个简单的实现可以实现rename(x, y)unlink(y) && link(x, y) && unlink(x).但是,如果xy是相同的名称,这将使文件在第一步中消失。

检查两个名称是否完全相同的字符串也是不够的,因为您可能会遇到类似的情况rename("../foo/x", "x")(当您坐在 时foo/),或更糟糕的是rename("/dir/symlink/x", "x")(符号链接将您带回到.)。检查两个字符串是否导致相同的文件名并不容易,但是调用stat()两者并检查设备和索引节点号以查看它们是否是相同的索引节点更容易。然后,当它们是两个不同的文件名但同一个文件时,您也会拒绝重命名。

这并不是说现代智能实现rename()不能做得更好,正如您所期望的那样,但它可能已经根据“它总是如何工作”进行了编码。 (结束猜测。)

相关内容