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