【问题标题】:Can hardlinks be overwritten without using a temporary file?可以在不使用临时文件的情况下覆盖硬链接吗?
【发布时间】:2015-05-24 16:38:03
【问题描述】:

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

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

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

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

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

是否有可能创建一个指向 inode 的链接来替换具有相同名称的旧链接?

【问题讨论】:

  • 你想改变什么,只是链接的name,或者它所在的(inode->)文件的实际contents链接到?
  • 我希望文件(目录项)指向不同的 inode。

标签: c linux system-calls inode


【解决方案1】:

您需要有另一个文件来切换链接。然而 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 起)

创建一个未命名的临时文件。路径名参数 指定目录;将创建一个未命名的 inode 该目录的文件系统。任何写到 当最后一个文件描述符为 关闭,除非文件被命名。

O_TMPFILE 必须使用O_RDWRO_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] 确实支持它,XFS 在 3.15 中也是如此; 3.16 中的 btrfs;此外,它可能仍然不适合您的情况,因为linkat 需要AT_SYMLINK_FOLLOW,而renameat 不可用;如果目标名称已经存在,`linkat 不会替换目标。

【讨论】:

  • 很遗憾必须创建一个临时文件。似乎有非官方的兴趣添加 AT_REPLACE 这将解决这个问题 [1] 但除此之外,临时文件是唯一的方法。 [1]:lwn.net/Articles/559969
猜你喜欢
  • 2014-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
相关资源
最近更新 更多