VOP_RENAME(9) FreeBSD カーネル開発者マニュアル VOP_RENAME(9)
名称
VOP_RENAME − ファイルの名前変更 |
書式
#include <sys/param.h> int |
VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp); |
解説 |
これはファイルの名前変更をし、もしかすると親ディレクトリを変更するかもし れません。変更先のオブジェクトが存在する場合には、最初に削除されます。 引数は以下のとおりです。 |
fdvp
古い親ディレクトリの vnode です。 fvp fcnp tdvp tvp tcnp ロック |
エントリ時には、変更元のディレクトリおよびファイルはロックされておらず、 それらの参照カウントは増やされています。この VOP ルーチンは戻る前に両方に 対して vrele(9) を呼び出すはずです。 変更先のディレクトリおよびファイルは、それらの参照カウントが増やされるの はもちろん、ロックされています。この VOP ルーチンは戻る前に両方に対して vput(9) を呼び出すはずです。 |
疑似コード
int vop_rename(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp, |
struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp) |
{ /* |
error = EXDEV; |
abortit: |
if (tdvp == tvp) |
|
vrele(tdvp); |
|
else |
|
vput(tdvp); |
|
if (tvp) |
|
vput(tvp); |
|
vrele(fdvp); |
|
vrele(fvp); |
|
return error; |
} if (tvp exists and is immutable) { |
error = EPERM; |
|
goto abortit; |
} /* |
if (fvp->v_type == VDIR) { |
|
error = EINVAL; |
|
goto abortit; |
|
} |
|
/* |
|
* 変更先を解放します。 |
|
*/ |
|
vput(tdvp); |
|
vput(tvp); |
|
/* |
|
* 変更元を削除します。少し異様な要素です。 |
|
*/ |
|
vrele(fdvp); |
|
vrele(fvp); |
|
fcnp->cn_flags &= ~MODMASK; |
|
fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; |
|
fcnp->cn_nameiop = DELETE; |
|
VREF(fdvp); |
|
error = relookup(fdvp, &fvp, fcnp); |
|
if (error == 0) |
|
vrele(fdvp); |
|
return VOP_REMOVE(fdvp, fvp, fcnp); |
} if (fvp is immutable) { |
error = EPERM; |
|
goto abortit; |
} error = VOP_LOCK(fvp); |
goto abortit; |
if (vp is a directory) { |
/* |
|
* 明白な理由のため、".", ".." と "." の別名を避けます。 |
|
*/ |
|
if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == ’.’) |
|
|| fdvp == fvp |
|
|| ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)) { |
|
VOP_UNLOCK(fvp); |
|
error = EINVAL; |
|
goto abortit; |
|
} |
|
doingdirectory = 1; |
} /* /* |
/* |
|
* パス名の衝突をチェックします。 |
|
*/ |
|
...; |
} /* |
/* |
||||
* 新しいディレクトリの ".." のアカウント。 |
||||
*/ |
||||
if (doingdirectory && fdvp != tdvp) { |
||||
/* |
||||
* tdvp のリンクカウントを増やします。 |
||||
*/ |
||||
...; |
||||
} |
||||
/* |
||||
* 新しいディレクトリで名前を追加します。 |
||||
*/ |
||||
...; |
||||
if (error) { |
||||
if (doingdirectory && fdvp != tdvp) { |
||||
/* |
||||
* tdvp であればリンクカウントを減らします。 |
||||
*/ |
||||
...; |
||||
} |
||||
goto bad; |
||||
} |
||||
vput(tdvp); |
} else { |
/* |
||||
* 変更先がディレクトリの場合、これは空でなければならず、これへの |
||||
* リンクがあってはなりません。また、変更元と変更先は一致する |
||||
* (両方ともディレクトリ、または両方ともディレクトリではない) |
||||
* ことを保証してください。 |
||||
*/ |
||||
if (tvp is a directory) { |
||||
if (tvp is not empty) { |
||||
error = ENOTEMPTY; |
||||
goto bad; |
||||
} |
||||
if (!doingdirectory) { |
||||
error = ENOTDIR; |
||||
goto bad; |
||||
} |
||||
/* |
||||
* ディレクトリが消え去ったため、名前キャッシュを更新します。 |
||||
*/ |
||||
cache_purge(tdvp); |
||||
} else if (doingdirectory) { |
||||
error = ENOTDIR; |
||||
goto bad; |
||||
} |
||||
/* |
||||
* fvp が指す tdvp の名前 tcnp を変更します。 |
||||
*/ |
||||
...; |
||||
/* |
||||
* 変更先ディレクトリが変更元と同じディレクトリにある場合には、 |
||||
* 変更先のディレクトリの親のリンクカウントを減らします。 |
||||
* ".." により、その親に対する戻り方向のリンクとなる事実を、 |
||||
* 説明するものです。 |
||||
*/ |
||||
if (doingdirectory && fdvp == tdvp) { |
||||
/* |
||||
* tdvp のリンクカウントを減らします。 |
||||
*/ |
||||
...; |
||||
} |
||||
vput(tdvp); |
||||
/* |
||||
* ディレクトリがもはやそれを指さないので、tvp のリンクカウントを |
||||
* 減らします。 |
||||
*/ |
||||
...; |
||||
if (doingdirectory) { |
||||
/* |
||||
* 古いディレクトリ tvp をきれいにします。 |
||||
*/ |
||||
...; |
||||
} |
||||
vput(tvp); |
} /* bad: |
vput(tvp); |
vput(tdvp); |
/* |
|
* fvp のリンクカウントをデクリメント |
|
*/ |
|
...; |
vput(fvp); |
vrele(fvp); |
return error; |
エラー
[EPERM]
ファイルが変更可能ではありません。 [EXDEV] [EINVAL] [ENOTDIR] [ENOTEMPTY] 関連項目 |
作者
このマニュアルページは Doug Rabson が書きました。 FreeBSD 10.0 July 24, 1996 FreeBSD 10.0 |