是否保证具有相同根的两个子目录位于同一个挂载的文件系统上?

Sto*_*row 6 linux filesystems mount rename

一个cpp我正在使用的文件创建一个目录,即mkdir( path, ... ),在路径来自一个环境变量(例如getenv( "FOO" );)。

例如,上面创建的$FOOis/foopath是 `/foo/newPath/'。

对于我的问题的情况下,有可能/foo/oldPath/存在,并且有内容(假设没有进一步的子目录),在这种情况下,我想从移动文件/foo/oldPath//foo/newPath

我的问题是:因为/foo/newPath/是作为$FOO, 即的子目录创建的/foo/newPath/并且/foo/oldPath/具有相同的父目录,所以是否保证两个目录都在同一个“挂载的文件系统”上?我对 Linux 上的挂载点和文件系统的了解充其量是微不足道的。

这个问题背后的背景是:如果/foo/newPath//foo/oldPath/保证在同一个挂载的文件系统上,我可以使用rename()比其他替代方法更容易地执行文件移动。该函数的手册页说,如果oldPathnewPath不在同一个“挂载的文件系统”上,它将失败。

cun*_*mp3 14

他们不能保证。这可能/foo/oldPath是一个挂载点。

但是,这可以通过运行mount | grep 'on /foo/oldPath' No output should表明该oldPath目录不是挂载点来轻松检查。

如果您使用嵌套目录,则需要更加小心,因为您可以在任何地方拥有安装点。

我不确定这是否是自动化的,但值得注意的是,mount 的第三个字段(空格分隔)是每行的安装点,因此可以使用 an cut -d ' ' -f 3来提取路径(您是否需要验证它是不仅仅是另一个挂载点的子字符串,例如/foo/oldPath/nested/mountPoint

如果您想将其转换为 C/C++ 代码,您可以使用system("mount | grep 'on /foo/oldPath'"),但我不会发誓。如果需要,您可能会在 StackOverflow 上获得更多的实现细节。

  • 检查不同文件系统的更好方法是比较各个 [`*stat(2)`](https://linux.die.net/man/2/stat) 返回值的 `st_dev` 属性调用。或者,[`rename(2)`](https://linux.die.net/man/2/rename) 将在不同文件系统上的源文件和目标文件中使用`EXDEV` 失败。 (7认同)
  • 此外,不推荐使用 `system()` /sf/ask/1393941251/ (2认同)

Ste*_*itt 5

由于各种原因(在其他答案中详细说明),您不应该尝试此操作:/foo/oldPath本身可能是挂载点,或者可能存在覆盖文件系统并阻止移动文件。您甚至可能会在单个文件上遇到绑定挂载,这也会在重命名文件时导致问题。

与其提前确定文件是否可以重命名,不如尝试重命名它们并处理错误。rename如果发生错误,将返回 -1,如果由于交叉安装问题而无法重命名,errno则将设置为EXDEV。然后您可以以另一种方式继续(复制和删除)。

通常,要确定两个文件系统对象是否在同一个文件系统上,您应该stat对它们运行并查看设备标识符(中的st_dev字段struct stat)。同一文件系统上的两个文件系统对象将具有相同的设备标识符。