SYMLINK(7)

名称
symlink - シンボリックリンクの扱い

シンボリックリンクの扱い
シンボリックリンクは、他のファイルへのポインタとして働くファイルです。 動作を理解するためには、ハードリンクの動作を理解する必要があります。 ファイルへのハードリンクは元のファイルとは区別できません。 なぜなら、ハードリンクは元のファイル名の下敷きとなるオブジェクトを 参照するからです。 ファイルに対する変更は、ファイルを参照するために使用する名前には依存しません。 ハードリンクは、ディレクトリを参照してはなりませんし、 他のファイルシステム上のファイルを参照してもなりません。 シンボリックリンクは、リンクされたファイルの名前を格納します。 すなわち、他の名前へのポインタです。 下敷きとなるオブジェクトを参照するわけではありません。 このため、シンボリックリンクは、ディレクトリを参照することができますし、 ファイルシステムをまたがることが可能です。

シンボリックリンクとこれが参照するオブジェクトは ファイルシステムの名前空間において共存しますので、 リンク自身と参照されるオブジェクトの区別に関して混乱が生じることがあります。 歴史的には、コマンドおよびシステムコールは、 場当たり的にそれぞれ独自のリンク追跡規則を採用してきました。 このシステムに実装されている、統一的なアプローチの規則をここに示します。 ユーザインタフェースをできる限り一貫性あるものとするために、 ローカルアプリケーションもまたこの規則を守ることが重要です。

シンボリックリンクの操作は、リンク自身への操作、 もしくはリンクによって参照されるオブジェクトへの操作によって実現されます。 後者の場合、アプリケーションまたはシステムコールがリンクを “追跡 (follow)” したと言います。 シンボリックリンクは他のシンボリックリンクを参照することができます。 この場合、シンボリックリンクではないオブジェクトが見付かるか、 存在しないファイルを参照するシンボリックリンクが見付かるか、 ループが検出されるまで、 リンクが手繰られます。 (ループ検出は、追跡可能なリンク数の上限を設定することにより実現されます。 この制限を超過する場合にはエラーとなります。)

議論すべき領域で異なるものが 3 つあります。それらは次の通りです:

1.  システムコールのファイル名引数として使用されるシンボリックリンク。
2.  ファイルツリーをたどらないユーティリティの コマンドライン引数として指定されるシンボリックリンク。
3.  ファイルツリーをたどる (traverse) ユーティリティが扱うシンボリックリンク (コマンドラインで指定されるもの、 およびファイル階層をたどるときに出会うものの両方です)。

  システムコール
最初の領域は、 システムコールのファイル名引数として使用されるシンボリックリンクです。

次の例外を除き、全システムコールはシンボリックリンクを追跡します。 例えば、 “afile” という名前のファイルを指すシンボリックリンク “slink” が存在する場合、システムコール “open("slink" ...)” はファイル “afile” のファイル記述子を返します。

リンクを追跡せずに、シンボリックリンク自身を操作するシステムコールが 9 つあります。 それらは次の通りです: lchflags(2), lchmod(2), lchown(2), lstat(2), lutimes(2), readlink(2), rename(2), rmdir(2), unlink(2) 。 remove(3) は unlink(2) の別名ですから、これもまたシンボリックリンクを追跡しません。 rmdir(2) は、シンボリックリンクに対して適用されると、エラー ENOTDIR で失敗します。

既存のシンボリックリンクの所有者およびグループの変更は、 lchown(2) システムコールにて可能です。 既存のシンボリックリンクの フラグ・アクセスパーミッション・所有者/グループ・修正時刻は、それぞれ lchflags(2), lchmod(2), lchown(2), lutimes(2) システムコールで変更可能です。 これらのうち、システムが使用するのはフラグのみであり、 アクセスパーミッションと所有者情報は無視されます。

4.4BSD システムは歴史的な 4BSD システムとは異なり、システムコール chown(2) がシンボリックリンクを追跡するように変更されました。 後になって、新しい chown(2) の制限が明らかになると、 lchown(2) システムコールが追加されました。

  ファイルツリーをたどらないコマンド
第 2 の領域は、 ファイルツリーをたどらないコマンドに対する コマンドラインのファイル名引数として指定されるシンボリックリンクです。

下に述べる例外を除き、コマンドは、 コマンドライン引数として指定されるシンボリックリンクを追跡します。 例えば、 “afile” という名前のファイルを指すシンボリックリンク “slink” が存在する場合、コマンド “cat slink” はファイル “afile” の内容を表示します。

この規則は、ファイルツリーをたどることもできるコマンドも含みます。 これを認識することが重要です。 例えば、コマンド “chown file” はこの規則に含まれますが、コマンド “chown -R file” は含まれません。 (後者は第 3 の領域で後述します。)

コマンドがシンボリックリンクを追跡するのではなく シンボリックリンク自身を操作する ことが明示的に意図されている場合、 例えば “chown slink” が、シンボリックリンクであるか否かにかかわらず、 “slink” 自身の所有者を変更したい場合、 -h オプションを使用します。 先の例では、 “chown root slink” は “slink” が参照するファイルの所有者を変更しますが、 “chown -h root slink” は “slink” 自身の所有者を変更します。

この規則には 4 つの例外があります。 mv(1) および rm(1) のコマンドは、引数として指定されるシンボリックリンクを追跡せずに、 それぞれシンボリックリンク自身を改名したり削除しようとします。 (シンボリックリンクがファイルを相対パスで指定する場合、 シンボリックリンクを他のディレクトリに移動してしまうと、 パスが正しくなくなってしまいますので、 追跡できなくなります。)

ls(1) コマンドもまたこの規則の例外です。 歴史的なシステムとの互換性のために ( ls がツリーをたどらない場合、すなわち -R オプションが指定されない場合)、 -H, -L オプションが指定されるか -F, -d, -l オプションが指定されない場合、 ls コマンドは引数として指定されたシンボリックリンクを追跡します。( ファイルツリーをたどらない場合にも、 -H, -L オプションが動作に影響を与えるコマンドは ls だけです。)

file(1) コマンドもまたこの規則の例外です。 file(1) コマンドは、引数として指定されるシンボリックリンクを、 デフォルトでは追跡しません。 -L オプションが指定されると、 file(1) コマンドは引数として指定されるシンボリックリンクを追跡します。

4.4BSD システムは歴史的な 4BSD システムとは異なり、 chown, chgrp のコマンドがコマンドラインに指定されたシンボリックリンクを追跡します。

  ファイルツリーをたどるコマンド
次のコマンドは、オプションとしてまたは常にファイルツリーをたどります: chflags(1), chgrp(1), chmod(1), cp(1), du(1), find(1), ls(1), pax(1), rm(1), tar(1), chown(8) 。

ファイルシステムをたどるときに出会うシンボリックリンクおよび コマンドライン引数として指定されるシンボリックリンクに対し、 次の規則が等しく適用されることを認識することが重要です。

最初の規則は、 ディレクトリ型ではない ファイルを参照するシンボリックリンクに対して適用されます。 シンボリックリンクに対して適用される操作は、 リンク自身に対してなされますが、 そうでない場合にはリンクは無視されます。

コマンド “rm -r slink directory” は “slink” を削除し、 “directory” のツリーをたどるときに出会うシンボリックリンクもまた削除します。 なぜなら、シンボリックリンクは削除可能であるためです。 いかなる場合も、 “slink” が参照するファイルに rm が影響することはありません。

第 2 の規則は、 タイプがディレクトリであるファイルを参照するシンボリックリンクに適用されます。 デフォルトでは、 タイプがディレクトリであるファイルを参照するシンボリックリンクは “追跡” されません。 これはしばしば “物理” 探索と呼ばれ、 “論理” 探索 (ディレクトリを参照するシンボリックリンクが追跡される場合です) の対極に位置します。

可能な限り一貫性を持たせるため、 シンボリックリンクが参照するファイルのタイプに依存せずに、 ファイルツリーをたどるコマンドに コマンドラインで指定されるシンボリックリンクを追跡させるためには、 -H (“半論理”) フラグを指定します。 このフラグは、 コマンドラインの名前空間を論理的な名前空間とすることを意図しています。 (注: 常にファイルツリーをたどるわけではないコマンドにおいては、 -R フラグも指定されていない場合には、 -H フラグは無視されます。)

例えば、コマンド “chown -HR user slink” は、 “slink” で指されるファイルを根とするファイル階層をたどります。 注: -H は、以前議論した -h フラグとは同じではありません。 -H フラグは、 実行される操作およびファイルツリーをたどるときの両方において、 コマンドラインで指定されるシンボリックリンクを手繰るようにします。 これにより、シンボリックリンクが指すファイルの名前を、 ユーザが指定したかのようになります。

可能な限り一貫性を持たせるため、 シンボリックリンクが参照するファイルのタイプに依存せずに、 ファイルツリーをたどるコマンドに コマンドラインで指定されるシンボリックリンクだけでなく ファイルツリーをたどっているときに出会うシンボリックリンクも 追跡させるためには、 -L (“論理”) フラグを指定します。 このフラグは、 すべての名前空間を論理的な名前空間とすることを意図しています。 (注: 常にファイルツリーをたどるわけではないコマンドにおいては、 -R フラグも指定されていない場合には、 -L フラグは無視されます。)

例えば、コマンド “chown -LR user slink” は、 “slink” で指されるファイルの所有者を変更します。 “slink” がディレクトリを参照する場合、 chown は “slink” で指されるディレクトリを根とするファイル階層をたどります。 さらに、 chown がたどるファイルツリーの中でシンボリックリンクに出会うと、 そのシンボリックリンクは “slink” と同じ方法で扱われます。

可能な限り一貫性を持たせるため、 デフォルトの動作を指定するには、 -P (“物理”) フラグを指定します。 このフラグは、 名前空間全体を物理的な名前空間のように見せるためのものです。

デフォルトでファイルツリーをたどらないコマンドにおいては、 -R もまた指定しない場合には、 -H, -L, -P フラグは無視されます。 また、 -H, -L, -P オプションは複数回指定可能です。 この場合、最後に指定したものがコマンドの動作を指定します。 ある動作を行うようにコマンドをエイリアスし、 それをコマンドラインで上書きできるようにすることを意図しています。

ls(1) と rm(1) のコマンドは、これらの規則において例外を持ちます。 rm コマンドはシンボリックリンクを操作し、 シンボリックリンクが参照するファイルを操作しません。 また、シンボリックリンクを追跡しません。 rm コマンドは -H, -L, -P のオプションをサポートしません。

歴史的なシステムとの互換性を維持するために、 ls コマンドは少し異なる挙動を示します。 -F, -d, -l オプションのいずれも指定しない場合、 ls コマンドは、コマンド行で指定したシンボリックリンクを追跡します。 -L フラグが指定されると、シンボリックリンクのタイプにかかわらず、 またコマンドラインで指定されたのかファイルツリーをたどる途中に 出会ったのにかもかかわらず、 ls は全シンボリックリンクを追跡します。

関連項目
chflags(1), chgrp(1), chmod(1), cp(1), du(1), find(1), ln(1), ls(1), mv(1), pax(1), rm(1), tar(1), lchflags(2), lchmod(2), lchown(2), lstat(2), lutimes(2), readlink(2), rename(2), symlink(2), unlink(2), fts(3), remove(3), chown(8)