数珠つなぎシンボリックリンク
シンボリックリンクでループしたときにエラーが出た,みたいな事を聞いて,「じゃあ,シンボリックリンクを数珠つなぎにしたらどこまでいけるんだろう?」と思ったのでやってみた.
シンボリックリンクの数珠つなぎは以下のようにした.
% cat sym.sh #!/bin/sh echo > 0 i=1 while [ $i -le 33 ]; do ln -s $((i-1)) $i i=$((i+1)) done % sh sym.sh % ls -l total 280 -rw-r--r-- 1 yasuhiko staff 1 2 6 09:18 0 lrwxr-xr-x 1 yasuhiko staff 1 2 6 09:18 1@ -> 0 ... lrwxr-xr-x 1 yasuhiko staff 2 2 6 09:18 30@ -> 29 lrwxr-xr-x 1 yasuhiko staff 2 2 6 09:18 31@ -> 30 lrwxr-xr-x 1 yasuhiko staff 2 2 6 09:18 32@ -> 31 lrwxr-xr-x 1 yasuhiko staff 2 2 6 09:18 33@ -> 32
ここで32, 33をcatとしてみると,33段目のシンボリックリンクが解決できないことがわかった.
% cat 32 % cat 33 cat: 33: Too many levels of symbolic links
ここで,ループしている云々よりも32段シンボリックリンクまでしか出来ないんじゃないの?という疑問が浮かんだ.
疑問:シンボリックリンクは32段までしかできない
そうしたら @ucq さんがこんなのを教えてくれた!
なるほど!Macではそうなっているのか!じゃあFreeBSDだとどうなっているんだろう?
そう思って調べてみると,/usr/src/sys/kern/vfs_lookup.c にそれらしいところがあった.namei()はファイルパスからvnode(inode)を探してくれる関数.
123 int 124 namei(struct nameidata *ndp) 125 { ... 244 for (;;) { ... 264 error = lookup(ndp); ... 280 if ((cnp->cn_flags & ISSYMLINK) == 0) { ... 296 return (0); 297 } ... 298 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 299 error = ELOOP; 300 break; 301 } ... 323 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); ... 351 } ... 363 }
264行目のlookup()でファイルパスからvnodeを取得.シンボリックリンクの場合はリンクを1つ解決.
280行目でシンボリックリンクじゃなければ終了.ここではシンボリックリンクを考えているので続く.
298行目でループ検出.MAXSYMLINKSを超えれば終了.
323行目でシンボリックリンクを解決して,再び264行目のlookup()へ.
という流れぽい
結論:シンボリックリンクを一つ解決するたびにループ検出用変数がインクリメントされて規定値を超えるとエラーになる.