xref: /freebsd/share/man/man9/VOP_RENAME.9 (revision a1a4f1a0d87b594d3f17a97dc0127eec1417e6f6)
1.\" -*- nroff -*-
2.\"
3.\" Copyright (c) 1996 Doug Rabson
4.\"
5.\" All rights reserved.
6.\"
7.\" This program is free software.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
19.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
22.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28.\"
29.\" $FreeBSD$
30.\"
31.Dd July 24, 1996
32.Os
33.Dt VOP_RENAME 9
34.Sh NAME
35.Nm VOP_RENAME
36.Nd rename a file
37.Sh SYNOPSIS
38.Fd #include <sys/param.h>
39.Fd #include <sys/vnode.h>
40.Ft int
41.Fn VOP_RENAME "struct vnode *fdvp" "struct vnode *fvp" "struct componentname *fcnp" "struct vnode *tdvp" "struct vnode *tvp" "struct componentname *tcnp"
42.Sh DESCRIPTION
43This renames a file and possibly changes its parent directory.
44If the destination object exists, it will be removed first.
45.Pp
46Its arguments are:
47.Bl -tag -width fdvp
48.It Ar fdvp
49the vnode of the old parent directory
50.It Ar fvp
51the vnode of the file to be renamed
52.It Ar fcnp
53pathname information about the file's current name
54.It Ar tdvp
55the vnode of the new parent directory
56.It Ar tvp
57the vnode of the target file (if it exists)
58.It Ar tcnp
59pathname information about the file's new name
60.El
61.Sh LOCKS
62The destination directory and file (if it exists) should be locked on entry.
63The source directory and file
64will be released on exit.
65The destination directory and file (if it exists) will be unlocked
66and released on exit.
67.Sh PSEUDOCODE
68.Bd -literal
69int
70vop_rename(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp,
71	   struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp)
72{
73    int doingdirectory = 0;
74    int error = 0;
75
76    /*
77     * Check for cross-device rename.
78     */
79    if (fvp->v_mount != tdvp->v_mount) {
80	error = EXDEV;
81    abortit:
82	VOP_ABORTOP(tdvp, tcnp);
83	if (tdvp == tvp)
84	    vrele(tdvp);
85	else
86	    vput(tdvp);
87	if (tvp)
88	    vput(tvp);
89	VOP_ABORTOP(fdvp, fcnp);
90	vrele(fdvp);
91	vrele(fvp);
92	return error;
93    }
94
95    if (tvp exists and is immutable) {
96	error = EPERM;
97	goto abortit;
98    }
99
100    /*
101     * Check if just deleting a link name.
102     */
103    if (fvp == tvp) {
104	if (fvp->v_type == VDIR) {
105	    error = EINVAL;
106	    goto abortit;
107	}
108
109	/*
110	 * Release destination.
111	 */
112	VOP_ABORTOP(tdvp, tcnp);
113	vput(tdvp);
114	vput(tvp);
115
116	/*
117	 * Delete source.  Pretty bizarre stuff.
118	 */
119	vrele(fdvp);
120	vrele(fvp);
121	fcnp->cn_flags &= ~MODMASK;
122	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
123	fcnp->cn_nameiop = DELETE;
124	VREF(fdvp);
125	error = relookup(fdvp, &fvp, fcnp);
126	if (error == 0)
127	    vrele(fdvp);
128	return VOP_REMOVE(fdvp, fvp, fcnp);
129    }
130
131    if (fvp is immutable) {
132	error = EPERM;
133	goto abortit;
134    }
135
136    error = VOP_LOCK(fvp);
137    if (error)
138	goto abortit;
139
140    if (vp is a directory) {
141	/*
142	 * Avoid ".", "..", and aliases of "." for obvious reasons.
143	 */
144	if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')
145	    || fdvp == fvp
146	    || ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)) {
147	    VOP_UNLOCK(fvp);
148	    error = EINVAL;
149	    goto abortit;
150	}
151	doingdirectory = 1;
152    }
153    vrele(fdvp);
154
155    /*
156     * Bump link count on fvp while we are moving stuff around.  If we
157     * crash before completing the work, the link count may be wrong
158     * but correctable.
159     */
160    ...;
161
162    /*
163     * If ".." must be changed (ie the directory gets a new
164     * parent) then the source directory must not be in the
165     * directory hierarchy above the target, as this would
166     * orphan everything below the source directory. Also
167     * the user must have write permission in the source so
168     * as to be able to change "..".
169     */
170    error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
171    VOP_UNLOCK(fvp);
172    if (doingdirectory && fdvp != tdvp) {
173	/*
174	 * Check for pathname conflict.
175	 */
176	...;
177    }
178
179    /*
180     * If the target doesn't exist, link the target to the source and
181     * unlink the source.  Otherwise, rewrite the target directory to
182     * reference the source and remove the original entry.
183     */
184    if (tvp == NULL) {
185	/*
186	 * Account for ".." in new directory.
187	 */
188	if (doingdirectory && fdvp != tdvp) {
189	    /*
190	     * Increase link count of tdvp.
191	     */
192	    ...;
193	}
194
195	/*
196	 * Add name in new directory.
197	 */
198	...;
199
200	if (error) {
201	    if (doingdirectory && fdvp != tdvp) {
202		/*
203		 * Decrease link count if tdvp.
204		 */
205		...;
206	    }
207	    goto bad;
208	}
209	vput(tdvp);
210    } else {
211	/*
212	 * Target must be empty if a directory and have no links
213	 * to it. Also, ensure source and target are compatible
214	 * (both directories, or both not directories).
215	 */
216	if (tvp is a directory) {
217	    if (tvp is not empty) {
218		error = ENOTEMPTY;
219		goto bad;
220	    }
221	    if (!doingdirectory) {
222		error = ENOTDIR;
223		goto bad;
224	    }
225	    /*
226	     * Update name cache since directory is going away.
227	     */
228	    cache_purge(tdvp);
229	} else if (doingdirectory) {
230	    error = ENOTDIR;
231	    goto bad;
232	}
233
234	/*
235	 * Change name tcnp in tdvp to point at fvp.
236	 */
237	...;
238
239	/*
240	 * If the target directory is in same directory as the source
241	 * directory, decrement the link count on the parent of the
242	 * target directory.  This accounts for the fact that a
243	 * directory links back to its parent with "..".
244	 */
245	if (doingdirectory && fdvp == tdvp) {
246	    /*
247	     * Decrement link count of tdvp.
248	     */
249	    ...;
250	}
251	vput(tdvp);
252
253	/*
254	 * Decrement the link count of tvp since the directory no
255	 * longer points at it.
256	 */
257	...;
258	if (doingdirectory) {
259	    /*
260	     * Clean up the old directory tvp.
261	     */
262	    ...;
263	}
264	vput(tvp);
265    }
266
267    /*
268     * Unlink the source.  If a directory was moved to a new parent,
269     * update its ".." entry.  Gobs of ugly UFS code omitted here.
270     */
271    ...;
272
273bad:
274    if (tvp)
275	vput(tvp);
276    vput(tdvp);
277out:
278    if (VOP_LOCK(fvp) == 0) {
279	/*
280	 * Decrement link count of fvp.
281	 */
282	...;
283        vput(fvp);
284    } else
285	vrele(fvp);
286
287    return error;
288}
289.Ed
290.Sh ERRORS
291.Bl -tag -width Er
292.It Bq Er EPERM
293the file is immutable
294.It Bq Er EXDEV
295cross device move
296.It Bq Er EINVAL
297illegal directory rename
298.It Bq Er ENOTDIR
299attempt to rename a directory to a file or vice versa
300.It Bq Er ENOTEMPTY
301attempt to remove a directory which is not empty
302.El
303.Sh SEE ALSO
304.Xr vnode 9
305.Sh AUTHORS
306This man page was written by
307.An Doug Rabson .
308