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