不使用临时文件可以覆盖硬链接吗?

Can hardlinks be overwritten without using a temporary file?

我很难link必须始终存在于文件系统上。 hardlink 分什么inode 不是常量。我想在不向目录添加临时条目的情况下更新 hardlink。

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

我面临的问题是 replacing/updating 困难link。从相关系统调用的文档来看,我似乎只有两个选择,而且都没有避免使用临时文件:

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

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

是否有可能创建一个 link 到 inode 以替换具有相同名称的旧 link?

您需要将 link 切换到另一个文件。然而 renamerenameat不需要inode在同一目录下link;他们只需要 inode 存在于同一个文件系统上,或者 更具体地说,存在于同一个挂载点 上;否则 Linux rename 失败 EXDEV:

EXDEV
oldpath and newpath are not on the same mounted filesystem. (Linux permits a filesystem to be mounted at multiple points, but rename() does not work across different mount points, even if the same filesystem is mounted on both.)


自 Linux 3.11 以来,有一种方法可以创建 new 文件,而无需 link 将其写入文件系统:open(2) has a new flag O_TMPFILE:

O_TMPFILE (since Linux 3.11)

Create an unnamed temporary file. The pathname argument specifies a directory; an unnamed inode will be created in that directory's filesystem. Anything written to the resulting file will be lost when the last file descriptor is closed, unless the file is given a name.

O_TMPFILE must be specified with one of O_RDWR or O_WRONLY and, optionally, O_EXCL. If O_EXCL is not specified, then linkat(2) can be used to link the temporary file into the filesystem, making it permanent, using code like the following:

      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);

In this case, the open() mode argument determines the file permission mode, as with O_CREAT.

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

Creating a file that is initially invisible, which is then populated with data and adjusted to have appropriate filesystem attributes (chown(2), chmod(2), fsetxattr(2), etc.) before being atomically linked into the filesystem in a fully formed state (using linkat(2) as described above).

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