UNIX V6から理解するディレクトリのx権限:それは「実行」ではなく、パス名を通すための探索権限である
1. はじめに
UNIXの権限を学ぶとき、多くの人が最初に引っかかるのが x 権限です。
通常ファイルに対する x は、直感的に理解しやすいです。
プログラムやシェルスクリプトを「実行できる」という意味だからです。
たとえば、次のようなファイルがあるとします。
text-rwxr-xr-x program
この場合、所有者は program を読み、書き、実行できます。
グループとその他ユーザーは、読み取りと実行ができます。
ここまでは分かりやすいです。
しかし、UNIXではディレクトリにも x が付きます。
textdrwxr-xr-x directory
ここで、多くの人がこう考えます。
「ディレクトリを実行するとは、どういう意味なのか?」
この疑問は正しいです。
ディレクトリはプログラムではありません。
ディレクトリをCPUが命令列として実行するわけではありません。
結論から言えば、ディレクトリの x は「実行権限」と呼ぶより、「探索権限」「検索権限」「通行権」と呼ぶほうが正確です。
この記事では、UNIX V6、すなわち Sixth Edition UNIX の実装を手がかりに、なぜディレクトリに x 権限が必要なのかを説明します。
特に重要なのは、UNIX V6のカーネル内部で、パス名を inode に変換する namei() という処理です。
この namei() の中で、途中のディレクトリに対して IEXEC が要求されています。
つまり、ディレクトリの x 権限は、あとから付けられた説明上の比喩ではありません。
UNIX V6の実装そのものが、パス名を解決する途中で、ディレクトリに x を要求しているのです。
2. UNIX V6とは何か
UNIX V6は、1975年5月の Sixth Edition UNIX、つまり第6版UNIXです。
K. Thompson と D. M. Ritchie による UNIX Programmer’s Manual Sixth Edition は、1975年5月の文書として残っています。
UNIX V6は、現代のLinuxやBSDとは違い、非常に小さなシステムです。
しかし、ファイルシステム、inode、ディレクトリ、パス名、所有者、グループ、rwx 権限といった、現在のUNIX系OSにつながる基本構造がすでに存在していました。
UNIX V6のファイルシステムでは、ファイルは単なる名前ではなく、inodeによって管理されます。
名前はディレクトリの中にあります。
ディレクトリは、名前と inode 番号を対応させる表です。
したがって、UNIXでファイルを開くとは、単に文字列としてのファイル名を見ることではありません。
text/home/sato/report.txt
このパスであれば、概念的には次のように処理されます。
text/ から始める
home という名前を探す
home に対応する inode を得る
sato という名前を探す
sato に対応する inode を得る
report.txt という名前を探す
report.txt に対応する inode を得る
最後に、その inode に対して読み取りや書き込みを行う
つまり、パス名は、ディレクトリを順番にたどるための道順です。
そして、その道順をたどるために必要なのが、ディレクトリの x 権限です。
3. inodeに格納されるmodeと権限
UNIX V6では、inode構造体の中に i_mode というフィールドがあります。
この i_mode に、ファイル種別と権限ビットが入っています。
UNIX V6の inode.h では、inodeについて「UNIXにおけるすべてのファイル活動の中心」と説明され、i_mode、所有者 i_uid、グループ i_gid、リンク数、サイズ、ブロックアドレスなどが inode に含まれています。
i_mode には、ファイル種別を表すビットと、権限を表すビットが同居しています。
代表的には、次のような定義があります。
textIFDIR 040000 ディレクトリ
IREAD 0400 読み取り
IWRITE 0200 書き込み
IEXEC 0100 実行・探索
ここで重要なのは、IEXEC が通常ファイルにもディレクトリにも同じビットとして使われることです。
通常ファイルであれば、IEXEC は本当に「実行できるか」を表します。
しかし、ディレクトリであれば、IEXEC は「そのディレクトリをパス名解決の途中で探索できるか」を表します。
同じビットですが、対象のファイル種別によって意味が変わるのです。
4. UNIX V6の実装で一番重要な関数:namei()
UNIX V6で、パス名を inode に変換する中心的な関数が namei() です。
namei() の役割は、文字列として渡されたパス名を読み取り、ルートディレクトリまたはカレントディレクトリから順にディレクトリをたどり、最後に目的の inode を返すことです。
たとえば、次のパスを考えます。
text/usr/lem/filex
namei() は、まず / から始めます。
次に usr を探します。
usr が見つかれば、その inode を取得します。
次に、その usr ディレクトリの中から lem を探します。
lem が見つかれば、その inode を取得します。
最後に filex を探します。
このように、namei() はパス名を左から右に分解し、各段階でディレクトリを検索します。
UNIX V6の nami.c には、まさにこの処理が書かれています。
コメントとして、パス名を inode へのポインタに変換する処理であることが示されています。
また、パスが / で始まる場合は rootdir から、そうでない場合はカレントディレクトリ u.u_cdir から開始する構造になっています。
ここで、ディレクトリの x 権限に関する決定的な処理が出てきます。
5. namei()は、途中のディレクトリにIEXECを要求する
UNIX V6の namei() には、次の趣旨の処理があります。
textパス名にまだ次の構成要素があるなら、
現在の inode はディレクトリでなければならない。
さらに、そのディレクトリには IEXEC 権限が必要である。
実装上は、現在の inode がディレクトリかどうかを IFDIR で確認し、ディレクトリでなければ ENOTDIR にします。
その次に、access(dp, IEXEC) を呼び出します。
ここで dp は、現在たどっているディレクトリの inode です。
この実装が、ディレクトリの x 権限を理解するうえで最重要です。
ディレクトリの x 権限は、「ディレクトリを実行するため」に確認されているのではありません。
パス名の次の構成要素へ進むために確認されています。
つまり、UNIX V6の実装では、ディレクトリの x は、パス名解決を前に進めるための条件です。
このことから、ディレクトリの x は次のように理解できます。
textディレクトリの x 権限
= そのディレクトリをパス名解決の途中で通過してよい権限
= そのディレクトリの中から、指定された名前を探してよい権限
= 探索権限、検索権限、通行権
これは説明上のたとえではなく、UNIX V6の namei() の構造から直接出てくる意味です。
6. ディレクトリは「名前→inode番号」の表である
ディレクトリの x 権限を正確に理解するには、ディレクトリの実体も理解する必要があります。
UNIX V6のディレクトリは、現代の感覚でいう「特殊なフォルダオブジェクト」というより、名前と inode 番号の対応表です。
UNIX V6では、ディレクトリエントリの名前部分は最大14文字です。
これは DIRSIZ として定義されています。
ディレクトリの中身は、概念的には次のような表です。
textinode番号 名前
2 bin
3 usr
15 tmp
パス名解決では、ディレクトリの中から、指定された名前と一致するエントリを探します。
一致したら、そのエントリに書かれている inode 番号を使って、次の inode を取得します。
UNIX V6の namei() でも、ディレクトリをブロック単位で読み、ディレクトリエントリを取り出し、名前を比較し、一致したら iget() で inode を取得する流れになっています。
ここでのポイントは、ディレクトリを通過するとは、ディレクトリという表の中から、次の名前を探し、対応する inode 番号を得ることだという点です。
そのために必要なのが、ディレクトリの x 権限です。
7. r権限とx権限は役割が違う
ディレクトリの r と x は、混同されやすいですが、役割が違います。
ディレクトリの r は、ディレクトリの一覧を読む権限です。
つまり、そのディレクトリにどのような名前があるかを見る権限です。
一方、ディレクトリの x は、特定の名前を使って、その先の inode に進む権限です。
この違いは、次のように整理できます。
textディレクトリの r
= 中にある名前一覧を読める
ディレクトリの x
= 既知の名前を使って、その inode に到達できる
部屋の例で言えば、r は部屋の中の目録を見る権限です。
x は部屋の扉を通る権限です。
目録が見えることと、部屋の中へ入れることは別です。
逆に、目録を見られなくても、書類の名前を正確に知っていれば、係員にその書類を出してもらえる場合があります。
UNIXのディレクトリ権限も同じです。
8. rだけあるディレクトリでは何が起きるか
ディレクトリに r だけがあり、x がない場合を考えます。
textdr--r--r-- dir
この場合、ディレクトリの一覧を読む権限はあります。
しかし、そのディレクトリをパス名解決の途中で通過する権限がありません。
そのため、ディレクトリ内の名前らしきものを取得できたとしても、個々のファイルへ到達できません。
これは、部屋の前に貼られた目録だけは見えるが、扉を通る許可がない状態です。
目録に report.txt と書いてあることは分かっても、部屋に入れないため、その書類には到達できません。
UNIX V6の実装で言えば、namei() が次の構成要素へ進むときに access(dp, IEXEC) を呼ぶため、IEXEC がなければそこで止まります。
つまり、ディレクトリの r は、パス名解決を前に進めるための権限ではありません。
パス名解決を前に進める本体は、ディレクトリの x です。
9. xだけあるディレクトリでは何が起きるか
次に、ディレクトリに x だけがあり、r がない場合を考えます。
textd--x--x--x dir
この場合、一覧を見ることはできません。
つまり、ls dir のようにして、ディレクトリ内の名前を列挙することはできません。
しかし、名前を正確に知っている場合は、その名前を指定して先へ進める可能性があります。
たとえば、次のファイルがあることを知っているとします。
textdir/report.txt
このとき、dir に x があり、report.txt 自体に読み取り権限があれば、report.txt を読むことができます。
これは一見不思議ですが、実装から考えると自然です。
namei() は、パス名として与えられた report.txt という名前を、ディレクトリの中で探します。
そのために必要なのが、親ディレクトリの x です。
一方、ディレクトリ内の名前一覧を利用者に列挙して見せる操作には、ディレクトリの r が必要です。
したがって、x だけのディレクトリは、次のような状態です。
text一覧は見せない
ただし、正確な名前を知っているものには到達させる
これは、実務でも使われる考え方です。
中身の一覧を隠しながら、特定の既知のパスだけを利用させたい場合に、この性質が意味を持ちます。
10. access()の実装:IEXECはどのように判定されるか
では、namei() が呼び出す access(dp, IEXEC) は、内部で何をしているのでしょうか。
UNIX V6の fio.c にある access() は、inodeに対して、読み取り、書き込み、実行のいずれかの権限があるかを確認する関数です。
access() の考え方は、概ね次の通りです。
text要求されたモードが IWRITE の場合は、読み取り専用ファイルシステムや実行中テキストを確認する
スーパーユーザーなら、原則として許可する
ただし IEXEC については、少なくともどれかの execute ビットが立っていなければ拒否する
通常ユーザーの場合は、所有者・グループ・その他のどれに該当するかを見て、判定対象ビットを右へシフトする
最終的に、inodeの i_mode と要求モードが一致すれば許可する
ここで、UNIX V6らしい重要な実装があります。
最初に要求モードは、所有者用のビットとして渡されます。
たとえば IEXEC は 0100 です。
現在のユーザーがファイル所有者でなければ、判定対象のモードを3ビット右へずらします。
これにより、所有者用の 0100 ではなく、グループ用の 0010 を見ることになります。
さらに、グループも一致しなければ、もう3ビット右へずらします。
これにより、その他ユーザー用の 0001 を見ることになります。
つまり、UNIX V6の access() は、次のように、要求側の m をずらして判定しています。
text所有者なら 0100 を見る
グループなら 0010 を見る
その他なら 0001 を見る
現代的に言えば、所有者・グループ・その他の権限欄を選んでいるわけです。
この実装により、access(dp, IEXEC) は、ディレクトリ dp に対して、現在のユーザーがそのディレクトリを探索できるかどうかを判定します。
11. スーパーユーザーでも、IEXECだけは完全な無条件許可ではない
UNIX V6の access() で面白いのは、スーパーユーザーの扱いです。
スーパーユーザー、つまり UID 0 であれば、基本的には権限チェックを通過できます。
しかし、IEXEC の場合だけは、少なくとも所有者・グループ・その他のどれかの実行ビットが立っていなければ拒否する実装になっています。
これは、通常ファイルの実行で特に意味があります。
まったく実行ビットの立っていないファイルを、スーパーユーザーだからといって何でも実行できるわけではない、という扱いです。
このルールは、ディレクトリにも同じ IEXEC ビットを使うため、考え方としてはディレクトリ探索にも影響します。
この点からも、UNIX V6では IEXEC が単なる「プログラム実行」専用の概念ではなく、inodeに対するアクセス種別のひとつとして実装されていることが分かります。
12. open()とexec()の違い:同じIEXECでも使われる場所が違う
通常ファイルの x とディレクトリの x は、同じ IEXEC ですが、使われる場所が違います。
通常ファイルを実行する場合は、exec() が関係します。
UNIX V6の exec() では、まず namei() でパス名から inode を取得します。
その後、access(ip, IEXEC) によって、その inode に実行権限があるかを確認します。
さらに、対象が特殊ファイルやディレクトリではなく、通常ファイルであることも確認します。
一方、ファイルを開く open() では、まず namei() がパス名を解決します。
この時点で、途中のディレクトリには IEXEC が要求されます。
その後、最後に得られた inode に対して、読み取りで開くなら IREAD、書き込みで開くなら IWRITE が確認されます。
つまり、同じ IEXEC でも、次の2つの場面があります。
text通常ファイルの IEXEC
= exec() によって、そのファイルを実行してよいかを確認する
ディレクトリの IEXEC
= namei() によって、そのディレクトリを通過してよいかを確認する
この違いを押さえると、「なぜディレクトリに実行権限があるのか」という疑問が解けます。
ディレクトリに対して exec() しているのではありません。
namei() がパス名解決のために IEXEC を使っているのです。
13. open()でファイルを読むとき、必要な権限は2段階である
ファイルを読むとき、多くの人は「ファイルに読み取り権限があれば読める」と考えます。
しかし、UNIXの実装では、それだけでは足りません。
たとえば、次のファイルを読むとします。
text/home/sato/report.txt
このとき必要な権限は、少なくとも次の2段階です。
text/、/home、/home/sato を通過するための x 権限
report.txt 自体を読むための r 権限
UNIX V6の実装で言えば、1は namei() の中で確認されます。
途中のディレクトリごとに access(dp, IEXEC) が呼ばれます。
2は、最後の inode が得られたあと、open1() の中で確認されます。
読み取りモードで開く場合は access(rip, IREAD) が呼ばれます。
このように、ファイルを読むという一見単純な操作も、内部では次のように分かれています。
textパスをたどる権限
最後のファイルを読む権限
この区別ができると、UNIX系OSの権限トラブルをかなり正確に診断できます。
14. creat()とunlink()では、親ディレクトリのw権限が効く
ディレクトリの w 権限も、実装から見ると意味が明確になります。
ファイルを作成する、削除する、名前を変えるという操作は、ファイルの中身を書き換える操作ではありません。
親ディレクトリの中にある「名前と inode 番号の対応表」を書き換える操作です。
UNIX V6の namei() では、ファイル作成用の探索では flag == 1、削除用の探索では flag == 2 が使われます。
作成の場合、目的の名前が見つからなければ、最後に親ディレクトリに対して IWRITE を確認します。
削除の場合も、最後の名前を削除する段階で、親ディレクトリに対して IWRITE を確認します。
つまり、UNIX V6の実装上、作成や削除で重要なのは、対象ファイルそのものの w ではなく、親ディレクトリの w です。
ただし、親ディレクトリを書き換えるためには、そこに到達して探索できなければなりません。
そのため、実務上はディレクトリの書き込みには w だけでなく x も必要になります。
textディレクトリの w
= 名前と inode 番号の対応表を書き換える権限
ディレクトリの x
= その対応表の中で、指定された名前をたどる権限
このように考えると、「ファイルを削除するには、なぜ親ディレクトリの権限が重要なのか」も理解できます。
15. ディレクトリのx権限を「部屋」で説明する
ここまでの実装の話を、直感的な例に戻して整理します。
ディレクトリを部屋だと考えます。
ファイルは、その部屋の中に置かれた書類です。
ディレクトリの中身、つまり名前と inode 番号の対応表は、部屋の中の目録です。
このとき、各権限は次のように説明できます。
textr 部屋の中の目録を読める
w 部屋の中の目録を書き換えられる
x 部屋の扉を通れる
r があれば、部屋の中にどのような名前の書類があるかを一覧できます。
w があれば、目録に新しい名前を追加したり、名前を消したりできます。
x があれば、その部屋を通過して、指定された書類や奥の部屋に進めます。
重要なのは、x が「部屋を実行する」権限ではないことです。
x は、部屋を通行する権限です。
UNIX V6の実装で言えば、この「扉を通る」処理が namei() の access(dp, IEXEC) に対応します。
16. rだけ、xだけ、rxありの違い
ディレクトリの r と x の組み合わせを、実務的に整理します。
rだけある場合
textdr--r--r-- dir
一覧を読む権限はあります。
しかし、通過する権限がありません。
したがって、名前の一覧が見えたとしても、その名前を使ってファイルに到達することはできません。
これは、目録は見えるが、部屋には入れない状態です。
xだけある場合
textd--x--x--x dir
一覧は見えません。
しかし、正確な名前を知っていれば、その名前を使って到達できる場合があります。
これは、目録は見せてもらえないが、書類名を正確に指定すれば取り出せる状態です。
rとxがある場合
textdr-xr-xr-x dir
一覧を見ることも、既知の名前に到達することもできます。
ただし、w がなければ、名前の追加や削除はできません。
これは、目録を見られ、部屋にも入れるが、目録を書き換えることはできない状態です。
wとxがある場合
textd-wx-wx-wx dir
一覧は見えません。
しかし、名前を知っていれば、作成や削除のような書き換え操作が可能になる場合があります。
実務では扱いに注意が必要な権限です。
17. chmod 644をディレクトリに設定すると危険な理由
通常ファイルでは、644 はよく使われます。
text-rw-r--r-- file
所有者は読み書きでき、グループとその他ユーザーは読み取りだけできます。
通常ファイルとしては自然な設定です。
しかし、同じ 644 をディレクトリに設定すると問題が起きます。
textdrw-r--r-- dir
ディレクトリに x がないため、パス名解決で通過できません。
一覧読み取りの r はありますが、ディレクトリの中にある名前を使って先へ進む権限がありません。
そのため、ディレクトリに対しては、読み取りを許可するなら、通常は x もセットで必要になります。
text通常ファイルの代表例
644 = rw-r--r--
ディレクトリの代表例
755 = rwxr-xr-x
これは丸暗記ではなく、UNIX V6の実装から説明できます。
通常ファイルの読み取りでは、最後の inode に対して IREAD が必要です。
ディレクトリの通過では、途中のディレクトリに対して IEXEC が必要です。
だから、ファイルとディレクトリでは、同じ数字を機械的に使い回してはいけません。
18. 755をディレクトリとして読む
ディレクトリに対する 755 は、次の意味です。
textdrwxr-xr-x
所有者は、一覧を読み、名前表を書き換え、通過できます。
グループは、一覧を読み、通過できます。
その他ユーザーも、一覧を読み、通過できます。
つまり、ディレクトリとしての 755 は次の状態です。
text所有者 目録を読める、目録を書き換えられる、扉を通れる
グループ 目録を読める、扉を通れる
その他 目録を読める、扉を通れる
Web公開ディレクトリや、プログラム配置用ディレクトリで 755 がよく使われるのは、このためです。
中身を見せ、既知のファイルへ到達させるが、一般ユーザーには名前表を書き換えさせない、という構成です。
19. 711をディレクトリとして読む
ディレクトリに対する 711 は、次の意味です。
textdrwx--x--x
所有者は、一覧を読み、書き換え、通過できます。
グループとその他ユーザーは、一覧を見ることはできません。
しかし、正確な名前を知っていれば通過できます。
これは、次のような性質を持つディレクトリです。
text中身の一覧は隠す
ただし、既知の名前には到達させる
たとえば、ホームディレクトリや公開用の限定パスで、この考え方が使われることがあります。
ただし、実務ではセキュリティ設計を誤ると意図しないアクセスにつながるため、安易に使うべきではありません。
20. ディレクトリのx権限は、パス名の各段階で必要になる
ファイルアクセスで重要なのは、最後のファイルだけではありません。
経路上のすべてのディレクトリが関係します。
たとえば、次のファイルを読みたいとします。
text/a/b/c/report.txt
この場合、report.txt に読み取り権限があっても、それだけでは不十分です。
少なくとも、次のディレクトリを通過できなければなりません。
text/
/a
/a/b
/a/b/c
どこか1つでも x がなければ、そこでパス名解決が止まります。
UNIX V6の namei() は、パスの構成要素を1つずつ処理します。
そして、次の構成要素がある限り、現在の inode がディレクトリであることと、IEXEC 権限があることを確認します。
したがって、現代のLinuxやUNIX系OSで次のようなトラブルが起きた場合、最後のファイルだけを見るのは不十分です。
textファイルには読み取り権限があるのに読めない
Webサーバーからファイルが見えない
SFTPでパスを指定してもアクセスできない
アプリからログファイルが開けない
この場合は、経路上のディレクトリを順に確認する必要があります。
textnamei -l /a/b/c/report.txt
現代のLinuxでは、上記のようなコマンドでパス途中の権限を確認できます。
ただし、考え方自体はUNIX V6の時代から同じです。
パス名解決は、ディレクトリを1段ずつ通過する処理だからです。
21. 「ディレクトリを実行する」という説明がよくない理由
ディレクトリの x を「実行権限」とだけ説明すると、誤解が生まれます。
たしかに、権限表示では x です。
また、英語でも execute permission と呼ばれることがあります。
しかし、ディレクトリに対しては、CPUがディレクトリを命令列として実行しているわけではありません。
UNIX V6の実装を見ても、ディレクトリに対して exec() しているのではありません。
実際には、namei() がパス名を解決する途中で、ディレクトリに対して access(dp, IEXEC) を呼んでいます。
したがって、ディレクトリの x は、次のように説明すべきです。
textファイルの x
= 実行権限
ディレクトリの x
= 探索権限
= 検索権限
= 通行権
教育上は、「ディレクトリの実行権限」という言い方だけで終わらせないほうがよいです。
「ディレクトリでは、xは実行ではなく通行」と言い換えると、理解がかなり安定します。
22. UNIX V6実装から見た、権限チェックの全体像
ここまでの話を、UNIX V6の実装に沿ってまとめると、次のようになります。
パス名解決
textnamei()
パス名を左から右へ読み、ディレクトリを順にたどります。
途中の inode がディレクトリでなければ ENOTDIR です。
途中のディレクトリに IEXEC がなければ EACCES です。
権限判定
textaccess(inode, mode)
inode の i_mode を見て、現在のユーザーに要求された権限があるかを確認します。
所有者、グループ、その他のどれに該当するかによって、判定するビットを切り替えます。
ファイルを開く
textopen()
open1()
まず namei() でパス名を inode に変換します。
この時点で、途中のディレクトリの IEXEC が確認されます。
その後、最後の inode に対して、読み取りなら IREAD、書き込みなら IWRITE が確認されます。
ファイルを実行する
textexec()
まず namei() でパス名を inode に変換します。
この時点で、途中のディレクトリの IEXEC が確認されます。
その後、最後の inode に対して IEXEC が確認されます。
ファイルを作る・消す
textcreat()
unlink()
親ディレクトリの中にある名前表を変更するため、親ディレクトリの IWRITE が関係します。
ただし、そこへ到達するには IEXEC も必要です。
23. 本当の理解は「最後のファイル」ではなく「経路」を見ること
UNIXの権限を正しく理解するには、最後のファイルだけを見てはいけません。
text-rw-r--r-- report.txt
このファイルだけを見ると、誰でも読めそうに見えます。
しかし、親ディレクトリが次のようであればどうでしょうか。
textdrwx------ sato
この場合、所有者以外は sato ディレクトリを通過できません。
そのため、report.txt 自体に読み取り権限があっても、所有者以外はそこに到達できません。
つまり、ファイルアクセスは次の掛け算です。
text経路上のディレクトリを通れること
×
最後のファイルに必要な権限があること
どちらか一方が欠ければ、アクセスはできません。
UNIX V6の実装は、この考え方を非常に素朴な形で示しています。
namei() が経路をたどり、access() が各 inode の権限を判定する。
この組み合わせが、UNIXのファイルアクセスの基本です。
24. まとめ
ディレクトリの x 権限は、ディレクトリを実行するための権限ではありません。
UNIX V6の実装では、パス名を inode に変換する namei() が、途中のディレクトリに対して IEXEC を要求しています。
これは、次の構成要素へ進むためです。
つまり、ディレクトリの x は、パス名解決を前に進めるための探索権限です。
通常ファイルの x は、exec() によって、そのファイルをプログラムとして実行してよいかを確認するために使われます。
一方、ディレクトリの x は、namei() によって、そのディレクトリを通過してよいかを確認するために使われます。
同じ IEXEC というビットでも、使われる場面が違います。
ディレクトリを部屋にたとえるなら、次のようになります。
textr 目録を見る権限
w 目録を書き換える権限
x 扉を通る権限
この比喩は、単なる初心者向けの説明ではありません。
UNIX V6の実装を見ても、ディレクトリの x は、まさにパス名解決の途中で扉を通るための条件になっています。
したがって、ディレクトリの x 権限を説明するときは、次の一文が最も重要です。
textディレクトリのx権限とは、そのディレクトリをパス名の一部として通過し、指定された名前を探索するための権限である。
これが分かると、UNIXの権限は一気に見通しがよくなります。
r は見えること。
w は名前表を書き換えること。
x は通れること。
特にディレクトリについては、x を「実行」ではなく「通行」と理解すること。
これが、UNIX V6の実装から見ても、最も本質に近い説明です。
参考資料
UNIX Programmer’s Manual, Sixth Edition, K. Thompson and D. M. Ritchie, May 1975
UNIX V6 source code, sys/inode.h
UNIX V6 source code, sys/ken/nami.c
UNIX V6 source code, sys/ken/fio.c
UNIX V6 source code, sys/ken/sys1.c
UNIX V6 source code, sys/ken/sys2.c
