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