为什么目录的读取权限不显示索引节点号?

iBu*_*Bug 15 filesystems permissions directory inode

据我了解,目录的“读取”权限允许列出该目录下的所有名称,仅此而已。

基于对 FS 设计的普遍理解,如果一个目录存储为文件,那么它的内容除了文件名之外,还至少应该包含对其 inode 的引用。使用 Unix 的“一切都是文件”哲学,“读取”权限授予对目录本身的“文件内容”的访问权限,因此应该足以检索每个文件的索引节点号。然而,这种情况并非如此。

我在这里缺少什么?

Sté*_*las 26

正如@muru 所示,你绝对可以通过读取目录内容来获取 inode 编号(在任何 POSIX 系统上,而不仅仅是 Linux)(无论目录是否像早期的 Unices 一样被实现为普通文件)。

可能导致您认为自己做不到的原因是您尝试过

ls -i dir
Run Code Online (Sandbox Code Playgroud)

在您已阅读但没有搜索权限的目录上并看到:

file1: Permission denied
file2: Permission denied
Run Code Online (Sandbox Code Playgroud)

这是因为您的ls实现确实尝试lstat()对返回的每个条目执行 a readdir(),而不是仅d_ino在条目中打印。

并非所有实现都这样做。例如,lsksh93 的内置函数(如果在构建时包含并使用 启用builtin ls)会打印d_inoby 返回的内容,readdir()而不是lstat()ing 每个文件。

ls大多数实现使用检索 inode 编号的原因之一lstat()可能是,否则,您通常会为作为挂载点的文件获取错误的 inode 编号:

% ksh93 -o emacs
$ builtin ls
$ /bin/ls -i /
    21 bin        28 home-blank       6 lost+found      22 root       5 tmp
     2 boot        9 home-test       26 media            1 run        2 u
     8 cdrom      14 lib             17 mnt             15 sbin      13 usr
     1 dev        23 lib32       855691 opt             25 snap  229376 var
    19 etc        20 lib64           34 pool0           18 srv
    34 home        4 libx32           1 proc             1 sys
$ ls -i /
    21 bin        28 home-blank       6 lost+found      22 root       5 tmp
    24 boot        9 home-test       26 media           12 run        2 u
     8 cdrom      14 lib             17 mnt             15 sbin      13 usr
     3 dev        23 lib32       855691 opt             25 snap  229376 var
    19 etc        20 lib64           11 pool0           18 srv
265966 home        4 libx32           7 proc            16 sys
Run Code Online (Sandbox Code Playgroud)

了解对于作为挂载点的文件(如上面的 、 、),ksh93 的内置函数如何/boot给出/proc/sys文件ls系统中文件的 inode 编号,而/bin/ls(在我的例子中是 GNU ls)给出这些文件的有效 inode 编号,即根文件系统的 inode 编号已安装文件系统的目录。

无论如何, ls -id some/file都会对lstat()文件执行 a (ksh93ls实际上会执行 astat()使其不符合 POSIX 标准)。

$ ls -id /boot
     2 /boot
Run Code Online (Sandbox Code Playgroud)

(同时使用 ksh93 和 GNU ls)。


mur*_*uru 12

确实如此,至少在我尝试过的 Linux 系统上是这样:

设置:

mkdir foo
touch foo/bar
# remove as much permission as possible, so that the program still works (only leave `r`).
chmod ugo-wx foo
chmod ugo+r #incase your umask, caused it not to be set
sudo chown root:root foo -R
Run Code Online (Sandbox Code Playgroud)

与:

mkdir foo
touch foo/bar
# remove as much permission as possible, so that the program still works (only leave `r`).
chmod ugo-wx foo
chmod ugo+r #incase your umask, caused it not to be set
sudo chown root:root foo -R
Run Code Online (Sandbox Code Playgroud)

我得到:

% ./readinode foo
3933790 .
3932162 ..
3933910 bar
Run Code Online (Sandbox Code Playgroud)

  • 看起来“ls”和“stat”所做的不仅仅是这个程序。然后他们会触发错误并退出。 (4认同)
  • 是的,两者都不是绝对必要的,但我只是证明这可以在最少的访问权限下工作。 (3认同)

Mar*_*ler 3

“我错过了什么”

\n

不要认为您没有获取 inode 信息的主张是错误的 - 尽管 inode 的概念与非 UNIX 文件系统的映射不同。

\n

但我认为您缺少的是您将用户界面理想(“一切都是文件”)与实现细节混淆了:\n
\n我会说您只是试图对内部进行假设文件系统的结构与目录的概念太过分了。

\n

无论目录如何实现,访问语义都被定义\xe2\x80\x93 ,那里确实没有什么需要理解的(或者相反,误解);这就是它们的定义方式。文件系统的内部结构对此没有影响。

\n

个人备注

\n

我注意到“目录存储为文件”是文件系统实现目录的一种方式。这不是唯一的一个。本文解释了 Linux 内核中最古老的 POSIX 样式文件系统之一如何不处理像文件这样的小目录条目列表 \xe2\x80\x93 目录条目不存储在数据范围中,但是在哪里通常,数据范围描述符列表将驻留在小目录中,而对于大目录,它是一个 B+ 树,它本身存储在范围中(XFS 算法和数据结构第 3 版,第 17.5 节和 16.2 节)\xe2\ x80\x93 但没有什么比文件作为连续范围的映射更重要。

\n

因此,“目录内部只是一个文件”的假设确实不成立。\n
\n我真的不知道它上次保存 \xe2\x80\x93 XFS 是什么时候,是从 1993/94 年开始的,并且进入 Linux 已有 22 年了;ext3 和随后的 ext4 也有类似的块树方法来目录,并且 ext3 也自 2001 年以来就已经存在。老实说,我不知道在这里考虑 ext2 是否有意义 \xe2\x80\ x93 自 2008 年以来,我就没有设置过 ext2 文件系统,因为没有日志记录的 ext3 始终比它具有严格的优势,而且我发现 Linux 发行版和嵌入式工具往往以同样的方式看待它。

\n

  • 套接字问题:“一切都是文件;有些文件只是比其他文件更多。” (4认同)
  • (现在,我仍然不明白“一切都是文件”与他们发布的原始问题有什么关系。我想在文件系统级别,目录需要包含其所包含文件的文件名和索引节点号,_even if_ 目录本身以某种与常规文件完全不同的特殊方式存储。但出于一般性,特别是允许任意嵌套级别,尽可能像文件一样存储目录似乎确实很有意义。尽管如此,返回从“readdir()”到用户空间的索引节点号可能没有必要。) (3认同)