まず、この問題がなぜ発生するのかから考えましょう。
Windows の大抵のツールは、
ディレクトリ削除を実行する際に、
まずディレクトリの下にある全てのファイル(とディレクトリ)の
削除を実行します。
で、ディレクトリが空になってから、ディレクトリそのものを削除します。
ディレクトリがシンボリックリンクの場合、
シンボリックリンク出さされた先のディレクトリを、
Client からの命令に従って削除します。
その後、ディレクトリを削除しろ、という命令が飛んでくるのですが、
ここで始めて対象がシンボリックリンクであることを確認し、
シンボリックリンクの削除を実行します。
ここまでの段階だけを見ると、Samba が悪いように見えます。
Windows がシンボリックリンクを知らないから悪いのであって、
それをちゃんと対処しない Samba が悪い、
と考えられるからです。
この考えは適切ではありません。
まずは unix のディレクトリに対するリンクの特徴から見ていきましょう。
ディレクトリに対するリンクには
ハードリンクとシンボリックリンクの両方があります。
POSIX 準拠の場合、
ディレクトリに対するハードリンクは root だけが実行できるのですが、
それでもハードリンクとシンボリックリンクの両方が可能です。
この「ディレクトリに対するリンク」という発想は、
実は unix が最初に採用したファイルシステム Interface の
弱点が色濃く継承されています。
そもそも、古典的なファイルシステムには、
ディレクトリを作成するための API は存在しませんでした。
mknod で directory 属性付きの inode と
block イメージとしてのディレクトリを作成し、
link 命令で '.' と '..' エントリを追加する、
というのがディレクトリの作り方だったのです。
この作り方をする限り、
1つのディレクトリに対して複数のリンクを張ることを
防止する方法はありません。
しかし一方で、
当時は unix はカーネルのソースコードを読んで使うもの、
というユーザーしかいなかったので、
この構造だからと言って
不用意にディレクトリの中のファイルを全て消してしまう、
というようなトラブルを起すような利用者はいませんでした。
問題はむしろ、
mknod と link という2つのコマンドが必要だったため、
ディレクトリ作成に atomicity がない、
という点にありました。
2つ以上のプログラムが同時にディレクトリを作成しようとしている場合、
ディレクトリイメージまでは作成できるのに link ができない、
という状態が発生してしまうのが問題だったのです。
この問題を解決するために、
SVR3 で mkdir と rmdir システムコールが作られ、
これを期にディレクトリを mknod で作製する方法は禁止されました。
当然、これに伴い unlink でディレクトリを削除するべきではない、
ともされました。
ディレクトリは rmdir で削除するべきだと。
しかし、ディレクトリに対するリンクは、
特にハードディスクの容量が少なかった昔は、便利なものでした。
unix はそもそもが制御ファイルがテキストファイルで肥大化し易く、
さらにソースコードが必ず存在していた、
という事実がこれに追い討ちをかけました。
include ファイルの多くはカーネルのソースコードのファイルと一致しており、
このためカーネルのディレクトリを丸々コピーするよりも
ディレクトリを丸ごとリンクしてファイルを共有した方が便利だったのです。
そして、この様なディレクトリ共有は、
ディレクトリそのものが read only な場合は全く問題を起しません。
このため、ディレクトリに対するリンク機構は存続することになりました。
その後、root だけに許されるように制限が強化されましたが、
それでもディレクトリに対するリンクを張ることは可能なままです。
当然、unlink も可能ですが、不適切な操作により、
ディレクトリ並びにその下にファイルが存在する状態のまま
ディレクトリに対する reference counter が 0 になってしまった場合、
基本的に、ファイルシステムは破綻を来たします。
この場合、破綻を解消するかどうか、また「どう解消するのか」は、
全てシステム依存になっています。
一方で、シンボリックリンクはハードリンクよりもさらに問題がやっかいです。
シンボリックリンクは基本的に、「つけ替え」作業しか行いません。
あるシンボル名は別の「シンボル名」に対する alias に過ぎません。
シンボル名が何を指しているのか、
あるいはそこに実体があるのかどうか、
は一切問題になりません。
当然、シンボリックリンクが指している先が、
ファイルになったり、ディレクトリになったりと、
その時々に応じて変化しても問題とはなりません。
シンボリックリンクは、
それがシンボリックリンクであることを検出する方法を提供し、
それに対してどうアプローチするのか、
という点を完全にアプリケーションに委ねてしまっています。
ここまでを要約すると、こうなります。
unix においては、
ディレクトリに対するリンクは、
ハードリンクであれソフトリンクであれ、
利用者が適切に利用することを前提とし、
システム(OS やファイルシステム)のレベルでは
なんらの危機防御機構を持ち合わせていないのです。
従って、ディレクトリに対するリンクは、
全て「利用者側の責任に置いて」作成され、
利用されなくてはいけません。
実はこの事実、Application プログラムが
必ず責任を取るようにコーディングできるわけではない
と言う重要な事実をも指摘しています。
そもそも、ここで必ず責任を取るようにコーディングできるのならば、
OS レベルでもそのように実装することも可能です。
そのように実装することはできない、
でも機能を切ることもできない、
だからユーザー側に責任を押し付けているのです。
そもそも、「1つの実体を2つの名前が指す」という状態の、
『意味』を考えてみましょう。
実は、答は少なくとも2つ、存在することが判ります。
1つ目は、2つの名前がおなじ実体を指しているのは、
あくまでも一つの実体を2つの名前で参照したいから、
という場合です。
この場合、
どちらの名前で参照している場合でも、
変更(削除は変更の一種)は一度に効果を持たなくてはいけません。
どちらかの名前で実体を削除する場合は、
その実体を指している全ての「リンク」を削除するのが
正しい有り様になります。
2つ目は、2つの名前は実は異なる実体を指したいのだが、
同じ内容であることが判っているので、
同じ内容の間は同じものを指し示そう、
というものです。
これは copy on modify モデルと言って、
昨今の unix ではプロセスを fork で増やす場合、
メモリ空間に対してこのモデルが使われます。
この場合、どちらかの名前で何らかの変更を要求した場合、
まず変更側がコピーされ、
それに対する変更が施されます。
この2つのどちらの意味で実装するのであっても、
「1つの実体を2つの名前が参照している」
状態は正しい状態を意味します。
しかし、逆に言えばアプリケーションはこの2つのどちらの意味なのかを
決定しなくてはいけません。
あるいは、両方を実装してユーザーに決定させる必要があります。
特に1つ目の場合はやっかいで、「1つの実体を消去する」事と、
「実体へのリンクを消去する」事は全く異なることになります。
unix には unlink() システムコールしかありませんから、
この作業は atomicity を欠いています。
あるファイルに対して「実体を削除するべく」全てのハードリンクを
消そうとしているアプリケーションと、
そのファイルに対するレプリカを作るべくどんどんリンクを作成し続ける
アプリケーションが同時に動いたら、
これはレース状態になってしまうでしょう。
下手をすれば、永久に止まりません。
ましてや、あるアプリケーション、あるユーザーが、
どちらの意味でディレクトリ構造に対するリンクを実装したとしても、
別のユーザー、別のアプリケーションが、
もう一方の意味で実装することを止めることはできませんし、
2つのアプリケーションが異なる意味で
ディレクトリに対するリンクを使い出したら、
当然矛盾が発生します。
具体例を上げてみましょう。
vi と emacs という、unix 上の 2 大エディターは、
今の所シンボリックリンクはちゃんとトレースして、
実体を変更するようになっていますが、
ハードリンクに対しては vi は実体に対する変更を、
emacs は copy on modify を意味します。
このように異なるアプリケーションは、
異なる結果をもたらすのです。
unix のディレクトリに対するリンク機構は、
最初から、
このように利用者の理解を要求します。
逆に言えば、これらの事実を理解せずに
ディレクトリに対してリンクを張っても、
望み通りの結果が得られず被害を被るだけであり、
その状態が「当然」なのです。
従って、任意のユーザーに公開するディレクトリに対して
何らかの形で多重リンクを張るべきではありません。
唯一の例外は、ディレクトリ並びにその中身が全て
read only の場合です。
この場合、変更・削除が生じる可能性はなくなり、
結果として矛盾が発生する可能性は0になります。
以上が unix のディレクトリに対するリンクの特徴です。
一方 Windows の方はと言うと、
これは比較的簡単です。
1つの実体に対して2つの名前を割り振る方法はありません。
いや、これは厳密には正しい表現ではありませんでした。
MS-DOS 2.11 の頃、MS-DOS にはディレクトリエントリーの
ファイル開始 FAT 番号を任意の番号にすり替えるインターフェースがありました。
これを利用すればディレクトリであろうがファイルであろうが、
任意のものに対する多重リンクに相当する構造を作ることは
可能でした。
ただしこの場合は、
この多重リンク対象のファイルやディレクトリを変更・削除することは
許されません。
他のインターフェースは多重リンクの存在を知らないまま
ファイルシステムを操作するので、
FAT 管理情報などが全て矛盾してしまうからです。
多重リンクを作れても、それが read only ではあまり実用性はありません。
単にファイルシステムが混乱する元が増えるだけです。
おそらくはそのためでしょう。
MS-DOS 3 以降、このインターフェースは削除され、
今もこれに相当するインターフェースは用意されていません。
Windows には「ショートカット」という特別なファイルが
あるかのように見えるかも知れませんが、
ショートカットは特別なファイルではありません。
ショートカットは Explorer が特別扱いする .lnk 拡張子を持ったファイルで、
その中身は Explorer がそのファイルをクリックした場合に
実行するべき内容が記述されているだけの、
通常ファイルです。
これが「通常ファイル」である最大の意味は、
「Windows という OS はこのファイルを特別扱いしない」
という事です。
普通のアプリケーションから見て、
このファイルは普通のファイルでしかなく、
別にそこに書かれているリンクを手繰ってくれるわけでも何でもありません。
実際、ショートカットの中に書かれているのは、
『そのファイルをクリックされたらどの様に挙動するべきか』
という挙動です。
これは一種のバッチファイルであり、
unix でいうシンボリックリンクなどとは全く意味が違います。
従って、ショートカットファイルをシンボリックリンクの代わりに
利用したり、Samba 側でシンボリックリンクをショートカットに
マップしたりするのは、全くのナンセンスです。
ましてや、ハードリンクに対する対策を考慮していない、
という点からも、このような発想は論外でしかありません。
結局の所、Samba は unix のディレクトリ管理システムに従うしかありません。
一方で、Samba は Client からのリクエストを1つづつ
忠実に実行することしかできません。
Client が掌握できない概念は Samba でも提供することはできませんから、
あるものが多重リンクである、
と言う事実を Windows に伝えることはできませんし、
その一方で Windows が「消せ」と言ってきたファイルやディレクトリは、
その実体が何であれ、消そうとする以外手はないのです。
従って、
Samba に公開するディレクトリを
多重リンクで作成してはいけない
という事実をキチンと守らなくてはいけない、
このルールに従うのは unix 側でリンクを張る人の義務である、
と言う事になります。
この要求は決して理不尽なものではありません。
Windows 側から Samba を経由して、ハードリンクであれ、
シンボリックリンクであれ、多重リンクを作ることはできません。
従って、Samba 経由で参照できるディレクトリ上に多重リンクが存在する場合、
その作者は unix 上でこの多重リンクを作成したことになります。
ということはこの作者は unix ファイルシステムの弱点を承知で
リンクを張った、と言う事であり、
その結果当然、守るべきルールを守っている、
事が要求されるからです。