シンボリックリンクが循環であることを確認するアルゴリズムはありますか?

シンボリックリンクが循環であることを確認するアルゴリズムはありますか?

Unixシステムでは、1回のパス検索で通過できるシンボリックリンクの数が制限されているため、シンボリックリンクサイクルを含むパスや、シンボリックリンクが多すぎるパスを検出するとエラーが発生することがよくあります。しかし、UNIXがフォローしようとするよりも多くのリンクが含まれていても、与えられたパスがどのように解決されるか、またはループを含むかどうかを実際に判断する方法はありますか?それとも正式に決定できない質問ですか?決定できれば、合理的な時間/メモリ内で(たとえば、ファイルシステム内のすべてのファイルにアクセスせずに)決定できますか?

いくつかの例:

a/b/c/d
where a/b is a symlink to ../e
and e is a symlink to f
and f is a symlink to a/b

a/b/c/d
where a/b/c is a symlink to ../c

a/b/c/d
where a/b/c is a symlink to ../c/d

a/b/c/d
where a/b/c is a symlink to /a/b/e
where a/b/e is a symlink to /a/b/f
where a/b/f is a symlink to /a/b/g

編集する:

明確にするために、ファイルシステム内のループを見つけるのではなく、指定されたパスが決定されたファイル/ディレクトリで解決されるのか、まったく解決されないのかを決定する決定アルゴリズムを尋ねることです。たとえば、次のシステムにはループがありますが、指定されたパスはまだ正常にチェックされます。

/ -- a -- b
where b is a symlink to /a

明らかにディレクトリツリーにループがありますが、パスはa/b/b/b/b/bまだ/a

ベストアンサー1

私はあなたが何を求めているのか完全に理解していません。私がよく知らなかったら、ファイルを処理しながらこれを検出する方法がないかと尋ねるようです。私はこれが可能だとは思わない。

私が考えることができる唯一の方法は、ディレクトリツリーで特定のブランチを探し始める場所を見つけることです。

はい

$ tree 
.
`-- a
    `-- b
        |-- c
        |   `-- d
        |       `-- e -> ../../../../a/b
        `-- e -> e

5 directories, 1 file

このfindコマンドはこのループを検出しますが、実際にすべての情報を知らせるわけではありません。

$ find -L . -mindepth 15
find: File system loop detected; `./a/b/c/d/e' is part of the same file system loop as `./a/b'.
find: `./a/b/e': Too many levels of symbolic links

をブロックするためにランダムに15レベルを選択しましたfind。ただし、-mindepth表示されるディレクトリツリーに興味がない場合は、スイッチ()を削除できます。このfindコマンドはまだループを検出して停止します。

$ find -L . 
.
./a
./a/b
./a/b/c
./a/b/c/d
find: File system loop detected; `./a/b/c/d/e' is part of the same file system loop as `./a/b'.
find: `./a/b/e': Too many levels of symbolic links

MAXSYMLINKSしかし、Linux(最新バージョンの3.xカーネル)でデフォルトの40をオーバーライドするには、次のU&L Q&Aを参照してください。MAXSYMLINKSを増やす方法

シンボリックリンクコマンドの使用

symlinksFTPサイト管理者は、シンボリックリンクのために長すぎるまたはぶら下がっているツリーの問題を公開するのに役立つツールを使用できます。

場合によっては、このsymlinksツールを使用して問題のあるリンクを削除することもできます。

はい

$ symlinks -srv a
lengthy:  /home/saml/tst/99159/a/b/c/d/e -> ../../../../a/b
dangling: /home/saml/tst/99159/a/b/e -> e

glibcライブラリ

glibcライブラリはそれに関連するいくつかのC関数を提供しているようですが、彼らが何をしているのか、実際にどのように使用するのかを完全に理解していません。それで、私はそれらをあなたに指摘することができます。

マニュアルページには、名前付きman symlink関数の関数定義が表示されますsymlink()。説明はこうです。

Symlink() は、oldpath 文字列を含む newpath という名前のシンボリックリンクを作成します。

エラーの1つは、関数が次を返すことを示しています。

ELOOPはnewpathの解析中にあまりにも多くのシンボリックリンクを見つけました。

man path_resolutionまた、Unixがディスクエントリのパスを決定する方法を説明するマニュアルページに案内します。特にこのセクション。

If  the component is found and is a symbolic link (symlink), we first 
resolve this symbolic link (with the current lookup directory as starting 
lookup directory).  Upon error, that error is returned.  If the result is 
not a directory, an ENOTDIR error is returned.  If the resolution of the 
symlink is successful and returns a directory, we set the current lookup
directory to that directory, and go to the next component.  Note that the 
resolution process here involves recursion.  In order  to  protect  the 
kernel against stack overflow, and also to protect against denial of 
service, there are limits on the maximum recursion depth, and on the maximum 
number of symbolic links followed.  An ELOOP error is returned  when  the
maximum is exceeded ("Too many levels of symbolic links").

おすすめ記事