为什么无法通过inode操纵文件?

25
为什么仅仅知道文件的inode,就无法访问该文件,而不必搜索连接到该inode的文件呢?硬链接只包含名称和一个数字,告诉您在哪里找到具有有关文件所有真实信息的inode。当我被告知没有用户模式的方法可以直接使用inode号码打开文件时,我感到惊讶。
这似乎是系统提供的一项无害且有用的功能。为什么不提供呢?

2
这样做的用例是什么? - user562374
@user 这个问题的灵感来自于这个问题。https://dev59.com/dFPTa4cB1Zd3GeqPgiMY 我也可以看到它被用来将文件传递给另一个有权访问该文件但没有权限访问我的目录结构的用户。 - Null Set
5
这正是不允许访问的原因。如果允许通过索引节点号访问文件,你可以尝试每个索引节点号,并绕过所有目录权限。 - R.. GitHub STOP HELPING ICE
一个使用案例是确保打开与已经打开的某人相同的文件。在UNIX上,文件名可能同时指向其他文件。 - user678269
1
但是如果您有文件名,您可以获取一个inode - 这种用例仍然适用于您。因此,如果您拥有它,您可以比较inodes并验证-samefile。但是,您不能仅通过inode直接进行操作。我想这就是我在这里得到的要点。 - mikeserv
5个回答

19

安全性考虑 -- 要访问文件,您需要对文件本身以及从根目录到该文件所需的所有目录具有访问权限。如果您可以通过inode访问文件,则可以绕过包含目录上的检查。

这使您可以创建一个只能被一组用户(或一组组)访问而不是其他人的文件 -- 创建仅可由用户访问的目录(每个用户一个目录),然后将文件硬链接到所有这些目录中 -- 文件本身可以被任何人访问,但只有在它链接到的其中一个目录具有搜索权限的人才能实际访问它。


4
访问文件的假设能力可以通过inode号码被限制为“root”用户。 - Keith Thompson

18
一些操作系统确实具备该功能。例如,OS X需要它来支持Carbon文件管理器,而在Linux上,您可以使用debugfs。当然,在任何UNIX系统上,您都可以通过命令行使用find -inum来执行此操作,但无法通过inode访问文件的真正原因是它并不特别有用。它确实绕过了文件权限,因为如果在一个您无法读取或执行的文件夹中有一个您可以读取的文件,那么打开inode就可以发现它。
它之所以不太有用是因为您需要通过*stat()调用找到一个inode号码,而此时您已经拥有文件名(或打开的文件描述符)…或者您需要猜测inode号码。

4
如果您关闭文件,然后稍后想要重新打开它,您就不必对其进行状态检查。 - johnnycrash
@johnnycrash 那会给你什么?你不可能在即将使用的某个极慢的存储介质上谈论任何有意义的性能提升。 - user23743
3
@johnnycrash,实际上您不能确定您打开的是否是同一个文件:相同的inode可能已被文件系统销毁并重新用于新文件,并且您无法检查这是否发生。 - pqnet
1
当你的文件系统变大时,这一点非常重要。当你有拥有 8TB 硬盘和 1.5 亿个待迭代的文件时,可以使速度提高几百倍。 - Lothar

4

针对您的评论:要“传递文件”,您可以通过使用SCM_RIGHTS在AF_LOCAL套接字上传递fd(请参见man 7 unix)。


4
Btrfs确实有一个ioctl(BTRFS_IOC_INO_PATHS,在此补丁中添加),但它并不尝试检查路径权限,而且仅保留给root用户使用。

2

如果您已经通过路径查找过文件,那么您就不需要一遍又一遍地重复这个过程了吧?

此内容涉及IT技术。
stat(f,&s); i=open(f,O_MODE);

涉及两次遍历目录结构。这会浪费CPU周期进行不必要的字符串操作。是的,设计良好的文件系统缓存将会隐藏大部分这种低效性对于普通用户来说,但是无缘无故地重复工作是丑陋的,如果不是愚蠢的话。

你可以将inode存储在数据库中,避免多次访问,这样可以节省数十毫秒的时间,而不是字符串操作的纳秒级别。如果对inode号码进行排序,速度会快1000倍,特别是在大量数据时。 - Lothar
这给了我一些想法。@Lothar的评论非常准确:如果您通过文件系统绕过名称使用,则基本上必须使用数据库实现某些等效功能。如果您一遍又一遍地打开相同的文件,并且希望唯一的真正问题是避免在同一目录中解析数百万个文件...解决方案?只需在包含较少文件的目录中创建这些文件的硬链接。这将避免大多数丢失的CPU周期,基本上执行与通过inode访问几乎相同的操作。 - kriss

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