xref: /freebsd/share/man/man9/VOP_RENAME.9 (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
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.In sys/param.h
39.In 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 Fa fdvp
49the vnode of the old parent directory
50.It Fa fvp
51the vnode of the file to be renamed
52.It Fa fcnp
53pathname information about the file's current name
54.It Fa tdvp
55the vnode of the new parent directory
56.It Fa tvp
57the vnode of the target file (if it exists)
58.It Fa tcnp
59pathname information about the file's new name
60.El
61.Sh LOCKS
62The source directory and file are unlocked but are expected to have their
63ref count bumped on entry.
64The VOP routine is expected to
65.Xr vrele 9
66both prior
67to returning.
68.Pp
69The destination directory and file are locked as well as having their ref
70count bumped.
71The VOP routine is expected to
72.Xr vput 9
73both prior to
74returning.
75.Sh PSEUDOCODE
76.Bd -literal
77int
78vop_rename(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp,
79	   struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp)
80{
81    int doingdirectory = 0;
82    int error = 0;
83
84    /*
85     * Check for cross-device rename.
86     */
87    if (fvp->v_mount != tdvp->v_mount) {
88	error = EXDEV;
89    abortit:
90	if (tdvp == tvp)
91	    vrele(tdvp);
92	else
93	    vput(tdvp);
94	if (tvp)
95	    vput(tvp);
96	vrele(fdvp);
97	vrele(fvp);
98	return error;
99    }
100
101    if (tvp exists and is immutable) {
102	error = EPERM;
103	goto abortit;
104    }
105
106    /*
107     * Check if just deleting a link name.
108     */
109    if (fvp == tvp) {
110	if (fvp->v_type == VDIR) {
111	    error = EINVAL;
112	    goto abortit;
113	}
114
115	/*
116	 * Release destination.
117	 */
118	vput(tdvp);
119	vput(tvp);
120
121	/*
122	 * Delete source.  Pretty bizarre stuff.
123	 */
124	vrele(fdvp);
125	vrele(fvp);
126	fcnp->cn_flags &= ~MODMASK;
127	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
128	fcnp->cn_nameiop = DELETE;
129	VREF(fdvp);
130	error = relookup(fdvp, &fvp, fcnp);
131	if (error == 0)
132	    vrele(fdvp);
133	return VOP_REMOVE(fdvp, fvp, fcnp);
134    }
135
136    if (fvp is immutable) {
137	error = EPERM;
138	goto abortit;
139    }
140
141    error = VOP_LOCK(fvp);
142    if (error)
143	goto abortit;
144
145    if (vp is a directory) {
146	/*
147	 * Avoid ".", "..", and aliases of "." for obvious reasons.
148	 */
149	if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')
150	    || fdvp == fvp
151	    || ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)) {
152	    VOP_UNLOCK(fvp);
153	    error = EINVAL;
154	    goto abortit;
155	}
156	doingdirectory = 1;
157    }
158    vrele(fdvp);
159
160    /*
161     * Bump link count on fvp while we are moving stuff around.  If we
162     * crash before completing the work, the link count may be wrong
163     * but correctable.
164     */
165    ...;
166
167    /*
168     * If ".." must be changed (ie the directory gets a new
169     * parent) then the source directory must not be in the
170     * directory hierarchy above the target, as this would
171     * orphan everything below the source directory. Also
172     * the user must have write permission in the source so
173     * as to be able to change "..".
174     */
175    error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
176    VOP_UNLOCK(fvp);
177    if (doingdirectory && fdvp != tdvp) {
178	/*
179	 * Check for pathname conflict.
180	 */
181	...;
182    }
183
184    /*
185     * If the target doesn't exist, link the target to the source and
186     * unlink the source.  Otherwise, rewrite the target directory to
187     * reference the source and remove the original entry.
188     */
189    if (tvp == NULL) {
190	/*
191	 * Account for ".." in new directory.
192	 */
193	if (doingdirectory && fdvp != tdvp) {
194	    /*
195	     * Increase link count of tdvp.
196	     */
197	    ...;
198	}
199
200	/*
201	 * Add name in new directory.
202	 */
203	...;
204
205	if (error) {
206	    if (doingdirectory && fdvp != tdvp) {
207		/*
208		 * Decrease link count if tdvp.
209		 */
210		...;
211	    }
212	    goto bad;
213	}
214	vput(tdvp);
215    } else {
216	/*
217	 * Target must be empty if a directory and have no links
218	 * to it. Also, ensure source and target are compatible
219	 * (both directories, or both not directories).
220	 */
221	if (tvp is a directory) {
222	    if (tvp is not empty) {
223		error = ENOTEMPTY;
224		goto bad;
225	    }
226	    if (!doingdirectory) {
227		error = ENOTDIR;
228		goto bad;
229	    }
230	    /*
231	     * Update name cache since directory is going away.
232	     */
233	    cache_purge(tdvp);
234	} else if (doingdirectory) {
235	    error = ENOTDIR;
236	    goto bad;
237	}
238
239	/*
240	 * Change name tcnp in tdvp to point at fvp.
241	 */
242	...;
243
244	/*
245	 * If the target directory is in same directory as the source
246	 * directory, decrement the link count on the parent of the
247	 * target directory.  This accounts for the fact that a
248	 * directory links back to its parent with "..".
249	 */
250	if (doingdirectory && fdvp == tdvp) {
251	    /*
252	     * Decrement link count of tdvp.
253	     */
254	    ...;
255	}
256	vput(tdvp);
257
258	/*
259	 * Decrement the link count of tvp since the directory no
260	 * longer points at it.
261	 */
262	...;
263	if (doingdirectory) {
264	    /*
265	     * Clean up the old directory tvp.
266	     */
267	    ...;
268	}
269	vput(tvp);
270    }
271
272    /*
273     * Unlink the source.  If a directory was moved to a new parent,
274     * update its ".." entry.  Gobs of ugly UFS code omitted here.
275     */
276    ...;
277
278bad:
279    if (tvp)
280	vput(tvp);
281    vput(tdvp);
282out:
283    if (VOP_LOCK(fvp) == 0) {
284	/*
285	 * Decrement link count of fvp.
286	 */
287	...;
288        vput(fvp);
289    } else
290	vrele(fvp);
291
292    return error;
293}
294.Ed
295.Sh ERRORS
296.Bl -tag -width Er
297.It Bq Er EPERM
298The file is immutable.
299.It Bq Er EXDEV
300It is not possible to rename a file between different file systems.
301.It Bq Er EINVAL
302An attempt was made to rename
303.Pa \&.
304or
305.Pa .. ,
306or to perform an operation which would break the directory tree structure.
307.It Bq Er ENOTDIR
308An attempt was made to rename a directory to a file or vice versa.
309.It Bq Er ENOTEMPTY
310An attempt was made to remove a directory which is not empty.
311.El
312.Sh SEE ALSO
313.Xr vnode 9
314.Sh AUTHORS
315This manual page was written by
316.An Doug Rabson .
317