是否可以在不使用临时文件的情况下覆盖硬链接?

时间:2015-03-21 08:11:17

标签: c linux system-calls inode

我有一个必须始终存在于文件系统上的硬链接。硬链接点的inode不是恒定的。我想更新硬链接而不添加临时条目到目录。

(创建没有目录条目的文件可以使用open(2)和temp标志来完成。)

我面临的问题是更换/更新硬链接。从相关系统调用的文档来看,似乎我只有两个选项,并且都没有避免临时文件:

  1. 使用renameat,可以确保硬链接始终存在。但是,它必须使用硬链接,因此需要临时文件(更不用说它无法取消引用符号链接)。

  2. 使用linkat,可以在不牺牲其他文件的情况下生成硬链接。但它不能覆盖现有文件;要求删除原始硬链接。

  3. 是否可以创建指向替换旧名称相同名称的inode的链接?

1 个答案:

答案 0 :(得分:3)

您需要有另一个文件可以切换链接。然而 renamerenameat不需要将inode链接到同一目录中;它们只需要inode存在于同一个文件系统中,或者更具体地说是在同一个挂载点上;否则Linux rename会失败并显示EXDEV

  

EXDEV
  oldpathnewpath不在同一个挂载的文件系统上。 (Linux允许在多个点安装文件系统,但rename()不能在不同的位置上运行                 挂载点,即使两者都安装了相同的文件系统。)


从Linux 3.11开始,有一种方法可以创建一个 new 文件,而无需将其链接到文件系统:open(2) has a new flag O_TMPFILE

  

O_TMPFILE(自Linux 3.11起)

     

创建一个未命名的临时文件。 pathname参数         指定目录;将创建一个未命名的inode         该目录的文件系统。写的任何东西         当最后一个文件描述符时,结果文件将丢失         关闭,除非文件被赋予名称。

     必须使用O_TMPFILEO_RDWR之一指定

O_WRONLY         并且,可选地,O_EXCL。如果未指定O_EXCL,则         linkat(2)可用于将临时文件链接到         文件系统,使其成为永久性的,使用类似的代码         以下内容:

      char path[PATH_MAX];
      fd = open("/path/to/dir", O_TMPFILE | O_RDWR,
                              S_IRUSR | S_IWUSR);
      /* File I/O on 'fd'... */
      snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);
      linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file",
                              AT_SYMLINK_FOLLOW);
     

在这种情况下,open()模式参数确定文件         权限模式,与O_CREAT一样。

手册告诉O_TMPFILE的两个常见用例之一是

  

创建一个最初不可见的文件,然后是             填充数据并调整为适当的             文件系统属性(chown(2),chmod(2),fsetxattr(2),             在原子地链接到文件系统之前             处于完全形成状态(使用如所述的linkat(2)             上文)。

除此之外还有很多不足之处:文件系统还必须支持O_TMPFILE; ext [234]支持它,3.15中的XFS也支持它; 3.16中的btrfs;此外,它可能仍然不适合您的情况,因为linkat需要AT_SYMLINK_FOLLOW renameat不可用;如果目标名称已经存在,`linkat 替换目标。