cpp
我正在使用的文件创建一个目录,即mkdir( path, ... )
,其中路径来自环境变量(例如getenv( "FOO" );
)。
例如,上面创建的$FOO
is/foo
和path
是 `/foo/newPath/'。
对于我的问题场景,可能/foo/oldPath/
存在并具有内容(假设没有其他子目录),在这种情况下,我想将文件/foo/oldPath/
从/foo/newPath
.
我的问题是:因为/foo/newPath/
被创建为 的子目录,$FOO
即具有相同的父目录,是否可以保证两个目录都在同一个“挂载文件系统”上?我对 Linux 上的挂载点和文件系统的理解充其量是微不足道的。/foo/newPath/
/foo/oldPath/
这个问题背后的背景是:如果/foo/newPath/
并且/foo/oldPath/
保证在同一个挂载的文件系统上,我可以使用它rename()
来比其他替代方案更轻松地执行文件移动。oldPath
该函数的手册页说,如果newPath
不在同一个“挂载文件系统”上,它将失败。
他们不能保证。这可能
/foo/oldPath
是一个挂载点。但是,这可以通过运行轻松检查
mount | grep 'on /foo/oldPath'
No output should指示该oldPath
目录不是安装点。如果您使用嵌套目录,则需要更加小心,因为您可以在任何地方拥有挂载点。
我不确定这是否是自动的,但值得注意的是 mount 的第三个字段(空格分隔)是每行的安装点,因此
cut -d ' ' -f 3
可以使用 an 来提取路径(如果您需要验证它是不仅仅是另一个挂载点的子字符串,比如/foo/oldPath/nested/mountPoint
)如果你想把它翻译成 C/C++ 代码,你可以使用
system("mount | grep 'on /foo/oldPath'")
,但我不会发誓。如果您需要,您可能会在 StackOverflow 上获得更多的实现细节。您不应该尝试这样做,原因有很多(在其他答案中有详细说明):
/foo/oldPath
它本身可能是一个挂载点,或者可能存在覆盖文件系统并阻止移动文件。您甚至可以在单个文件上遇到绑定挂载,这在重命名文件时也会导致问题。与其尝试提前确定文件是否可以重命名,不如尝试重命名它们并处理错误。
rename
如果发生错误,将返回 -1,如果由于交叉安装问题而无法重命名,errno
则将设置为。EXDEV
然后,您可以以另一种方式继续(复制和删除)。通常,要确定两个文件系统对象是否在同一个文件系统上,您应该
stat
在它们上运行并查看设备标识符( 中的st_dev
字段struct stat
)。同一文件系统上的两个文件系统对象将具有相同的设备标识符。请注意,当您在 overlayfs 上运行时,您不能依赖
rename()
预先存在的目录。我认为您通常可以忽略这种可能性,如果您不编写通用文件管理工具...例如,包管理器...在这种情况下,您显然可能认为它是不可修复的(出于原子性原因)并想要依赖
redirect_dir
overlayfs的新格式。所以这更像是一个迂腐的说明,让你知道这是 Linux,如果我们不想,我们不遵守 POSIX,而且“保证”是一个非常强的词:)。
https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt
Overlayfs 在其他细节上已经不符合对 unix 文件系统的通常期望: