4.2BSD の rename() システムコールでこの設計上の決定がなされた理由を理解しようとしています。ここで解決しようとしているものは何もありません。動作自体の理論的根拠を理解するだけです。
4.2BSD では、ファイルのアトミックな名前変更/移動を許可する目的で rename() syscall が導入されました。4.3BSD-Reno/src/sys/ufs/ufs_vnops.c から:
/*
* If ".." must be changed (ie the directory gets a new
* parent) then the source directory must not be in the
* directory heirarchy above the target, as this would
* orphan everything below the source directory. Also
* the user must have write permission in the source so
* as to be able to change "..". We must repeat the call
* to namei, as the parent directory is unlocked by the
* call to checkpath().
*/
if (oldparent != dp->i_number)
newparent = dp->i_number;
if (doingdirectory && newparent) {
VOP_LOCK(fndp->ni_vp);
error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred);
VOP_UNLOCK(fndp->ni_vp);
したがって、このチェックが意図的に追加されたことは明らかです。私の質問は - なぜですか?この動作は直感的なはずですか?
これの影響は、アトミックに書き込むことができる別のディレクトリに書き込むことができないディレクトリ (書き込み可能なディレクトリにある) を移動できないことです。ただし、新しいディレクトリを作成し、リンクを移動して (ディレクトリへの読み取りアクセス権があると仮定して)、ディレクトリの書き込みビットを削除することはできます。アトミックに行うことはできません。
% cd /tmp
% mkdir stackoverflow-question
% cd stackoverflow-question
% mkdir directory-1
% mkdir directory-2
% mkdir directory-1/directory-i-cant-write
% echo "foo" > directory-1/directory-i-cant-write/contents
% chmod 000 directory-1/directory-i-cant-write/contents
% chmod 000 directory-1/directory-i-cant-write
% mv directory-1/directory-i-cant-write directory-2
mv: rename directory-1/directory-i-cant-write to directory-2/directory-i-cant-write: Permission denied
これで、アトミックに移動できない読み取り不可能なコンテンツを含む書き込み不可能なディレクトリが作成されました。ただし、パーミッションを変更し、新しいディレクトリを作成し、ln を使用して新しいリンクを作成し、パーミッションを変更することで、非アトミックに同じ効果を得ることができます。(読者への演習として残しておきます)
. と .. はすでに特別なケースになっているので、ソースが示唆するように、ディレクトリを書き込むことができない場合は「..」を変更できないという直感的なことを特に購入しません。コードの作成者が認識した正しい動作である以外に、これには何か理由がありますか? 書き込み可能なディレクトリ間で (書き込み不可の) ディレクトリをアトミックに移動できるようにした場合、何か悪いことが起こる可能性はありますか?