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