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