为什么linkat需要路径名而不是文件描述符?

3
以下代码摘自 Debian 的手册页面中的 open(2)段落,描述了 O_TMPFILE 标志:

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

代码背后的思想是创建一个匿名文件,该文件在文件系统中没有名称,而只有文件描述符。这意味着没有其他人知道该文件并且可以访问它。然后您写入该文件。最后,使用linkat为该文件命名。之后,该文件就可见了,所有其他人都可以访问它。这是一种完美的方式来处理下载文件,以确保只有完整的下载文件可以被其他程序使用。
但是,我认为linkat调用的方式看起来设计有缺陷。 linkat实际上是做什么的?它给文件描述符命名。这意味着该函数需要两个参数:文件描述符和名称。但是它不接受文件描述符作为参数,而是需要一个没有名称的文件的名称。这使得必须依赖已挂载的proc文件系统来为未命名的文件创建名称,以便能够将该名称传递给linkat。这看起来很奇怪,我不知道为什么有人会发明这个。
为什么要以这种方式实现它?为什么没有一个函数?
link_what_ever (int fd, char *name);

正如您所写的,O_TMPFILE创建了一个匿名文件,没有其他人知道该文件并且可以访问它。这就是它的作用,如果要保存存储在该文件中的信息,您可以简单地创建新文件并将隐藏文件复制到其中。Linkat与O_TMPFILE没有关联,它创建了一个现有文件的新链接(也称为硬链接)。 - LPs
请翻译以下与编程有关的内容,仅返回翻译文本:请勿编辑我的答案发表评论。 - Barmar
如果我的答案不起作用,你正在运行哪个内核版本?AT_EMPTY_PATH是在Linux 2.6.39中添加的。 - Barmar
3个回答

3

我认为你可以使用AT_EMPTY_PATH标志来实现你想要的功能。

linkat(fd, "", AT_FDCWD, "/path/for/file", AT_EMPTY_PATH);

当使用此标志时,它会创建到由olddirfd参数标识的文件的链接。
请注意,使用此标志需要调用者具有CAP_DAC_READ_SEARCH权限。

3

从查看Linux的git历史记录来看,2013年8月初提交了一次 提交 来统一两个接口,从而允许非特权用户使用linkat(...,AT_EMPTY_PATH), 但该提交在月底被撤销,原因是未明确挂载/proc环境下的安全影响。


1

linkat 的作用是什么?它为文件描述符命名。

不,你的假设是错误的:linkat(2),就像 link(2) 一样,旨在给文件(即创建硬链接)一个名称,它有点不同。它并没有专门为给匿名文件命名而设计。相反,它是一个通用接口,允许您为已经存在的文件 Y 创建一个新名称 X

你可以说有人可以实现另一个函数 name_anon_file(int fd, char *name),这确实是正确的,但是在 linkat(2) 上实现它并不难,所以你可以自己做到。

此外,并非每个 UNIX 变体都支持 O_TMPFILE,因此该函数在一般情况下并没有太大用处。


如何在没有挂载 proc 文件系统的情况下实现 name_anon_file - ceving
@ceving它做不到。无论如何,如果未安装/proc,你的状况都非常糟糕——例如ps(1)lsof(1)这样的东西都不能工作。 - Filipe Gonçalves

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接