1 /* $NetBSD: ext2fs_lookup.c,v 1.2 1997/08/04 09:11:00 bouyer Exp $ */ 2 3 /* 4 * Modified for NetBSD 1.2E 5 * May 1997, Manuel Bouyer 6 * Laboratoire d'informatique de Paris VI 7 */ 8 /* 9 * modified for Lites 1.1 10 * 11 * Aug 1995, Godmar Back (gback@cs.utah.edu) 12 * University of Utah, Department of Computer Science 13 */ 14 /* 15 * Copyright (c) 1989, 1993 16 * The Regents of the University of California. All rights reserved. 17 * (c) UNIX System Laboratories, Inc. 18 * All or some portions of this file are derived from material licensed 19 * to the University of California by American Telephone and Telegraph 20 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 21 * the permission of UNIX System Laboratories, Inc. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * This product includes software developed by the University of 34 * California, Berkeley and its contributors. 35 * 4. Neither the name of the University nor the names of its contributors 36 * may be used to endorse or promote products derived from this software 37 * without specific prior written permission. 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 42 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 49 * SUCH DAMAGE. 50 * 51 * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 52 */ 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/namei.h> 57 #include <sys/buf.h> 58 #include <sys/file.h> 59 #include <sys/mount.h> 60 #include <sys/vnode.h> 61 #include <sys/malloc.h> 62 #include <sys/dirent.h> 63 64 #include <ufs/ufs/quota.h> 65 #include <ufs/ufs/inode.h> 66 #include <ufs/ufs/ufsmount.h> 67 #include <ufs/ufs/ufs_extern.h> 68 69 #include <ufs/ext2fs/ext2fs_extern.h> 70 #include <ufs/ext2fs/ext2fs_dir.h> 71 #include <ufs/ext2fs/ext2fs.h> 72 73 extern int dirchk; 74 75 static void ext2fs_dirconv2ffs __P((struct ext2fs_direct *e2dir, 76 struct dirent *ffsdir)); 77 static int ext2fs_dirbadentry __P((struct vnode *dp, 78 struct ext2fs_direct *de, 79 int entryoffsetinblock)); 80 81 /* 82 * the problem that is tackled below is the fact that FFS 83 * includes the terminating zero on disk while EXT2FS doesn't 84 * this implies that we need to introduce some padding. 85 * For instance, a filename "sbin" has normally a reclen 12 86 * in EXT2, but 16 in FFS. 87 * This reminds me of that Pepsi commercial: 'Kid saved a lousy nine cents...' 88 * If it wasn't for that, the complete ufs code for directories would 89 * have worked w/o changes (except for the difference in DIRBLKSIZ) 90 */ 91 static void 92 ext2fs_dirconv2ffs( e2dir, ffsdir) 93 struct ext2fs_direct *e2dir; 94 struct dirent *ffsdir; 95 { 96 bzero(ffsdir, sizeof(struct dirent)); 97 ffsdir->d_fileno = e2dir->e2d_ino; 98 ffsdir->d_namlen = e2dir->e2d_namlen; 99 100 ffsdir->d_type = DT_UNKNOWN; /* don't know more here */ 101 #ifdef DIAGNOSTIC 102 /* 103 * XXX Rigth now this can't happen, but if one day 104 * MAXNAMLEN != E2FS_MAXNAMLEN we should handle this more gracefully ! 105 */ 106 if (e2dir->e2d_namlen > MAXNAMLEN) panic("ext2fs: e2dir->e2d_namlen\n"); 107 #endif 108 strncpy(ffsdir->d_name, e2dir->e2d_name, ffsdir->d_namlen); 109 110 /* Godmar thinks: since e2dir->e2d_reclen can be big and means 111 nothing anyway, we compute our own reclen according to what 112 we think is right 113 */ 114 ffsdir->d_reclen = DIRENT_SIZE(ffsdir); 115 } 116 117 /* 118 * Vnode op for reading directories. 119 * 120 * Convert the on-disk entries to <sys/dirent.h> entries. 121 * the problem is that the conversion will blow up some entries by four bytes, 122 * so it can't be done in place. This is too bad. Right now the conversion is 123 * done entry by entry, the converted entry is sent via uiomove. 124 * 125 * XXX allocate a buffer, convert as many entries as possible, then send 126 * the whole buffer to uiomove 127 */ 128 int 129 ext2fs_readdir(v) 130 void *v; 131 { 132 struct vop_readdir_args /* { 133 struct vnode *a_vp; 134 struct uio *a_uio; 135 struct ucred *a_cred; 136 int *a_eofflag; 137 u_long *a_cookies; 138 int ncookies; 139 } */ *ap = v; 140 register struct uio *uio = ap->a_uio; 141 int error; 142 size_t e2fs_count, readcnt; 143 struct m_ext2fs *fs = VTOI(ap->a_vp)->i_e2fs; 144 145 struct ext2fs_direct *dp; 146 struct dirent dstd; 147 struct uio auio; 148 struct iovec aiov; 149 caddr_t dirbuf; 150 off_t off = uio->uio_offset; 151 u_long *cookies = ap->a_cookies; 152 int ncookies = ap->a_ncookies; 153 154 e2fs_count = uio->uio_resid; 155 /* Make sure we don't return partial entries. */ 156 e2fs_count -= (uio->uio_offset + e2fs_count) & (fs->e2fs_bsize -1); 157 if (e2fs_count <= 0) 158 return (EINVAL); 159 160 auio = *uio; 161 auio.uio_iov = &aiov; 162 auio.uio_iovcnt = 1; 163 auio.uio_segflg = UIO_SYSSPACE; 164 aiov.iov_len = e2fs_count; 165 auio.uio_resid = e2fs_count; 166 MALLOC(dirbuf, caddr_t, e2fs_count, M_TEMP, M_WAITOK); 167 bzero(dirbuf, e2fs_count); 168 aiov.iov_base = dirbuf; 169 170 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 171 if (error == 0) { 172 readcnt = e2fs_count - auio.uio_resid; 173 for (dp = (struct ext2fs_direct *)dirbuf; 174 (char *)dp < (char *)dirbuf + readcnt; ) { 175 if (dp->e2d_reclen <= 0) { 176 error = EIO; 177 break; 178 } 179 ext2fs_dirconv2ffs(dp, &dstd); 180 if(dstd.d_reclen > uio->uio_resid) { 181 break; 182 } 183 if ((error = uiomove((caddr_t)&dstd, dstd.d_reclen, uio)) != 0) { 184 break; 185 } 186 off = off + dp->e2d_reclen; 187 if (cookies != NULL) { 188 *cookies++ = off; 189 if (--ncookies <= 0){ 190 break; /* out of cookies */ 191 } 192 } 193 /* advance dp */ 194 dp = (struct ext2fs_direct *) ((char *)dp + dp->e2d_reclen); 195 } 196 /* we need to correct uio_offset */ 197 uio->uio_offset = off; 198 } 199 FREE(dirbuf, M_TEMP); 200 *ap->a_eofflag = VTOI(ap->a_vp)->i_e2fs_size <= uio->uio_offset; 201 return (error); 202 } 203 204 /* 205 * Convert a component of a pathname into a pointer to a locked inode. 206 * This is a very central and rather complicated routine. 207 * If the file system is not maintained in a strict tree hierarchy, 208 * this can result in a deadlock situation (see comments in code below). 209 * 210 * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending 211 * on whether the name is to be looked up, created, renamed, or deleted. 212 * When CREATE, RENAME, or DELETE is specified, information usable in 213 * creating, renaming, or deleting a directory entry may be calculated. 214 * If flag has LOCKPARENT or'ed into it and the target of the pathname 215 * exists, lookup returns both the target and its parent directory locked. 216 * When creating or renaming and LOCKPARENT is specified, the target may 217 * not be ".". When deleting and LOCKPARENT is specified, the target may 218 * be "."., but the caller must check to ensure it does an vrele and vput 219 * instead of two vputs. 220 * 221 * Overall outline of ext2fs_lookup: 222 * 223 * check accessibility of directory 224 * look for name in cache, if found, then if at end of path 225 * and deleting or creating, drop it, else return name 226 * search for name in directory, to found or notfound 227 * notfound: 228 * if creating, return locked directory, leaving info on available slots 229 * else return error 230 * found: 231 * if at end of path and deleting, return information to allow delete 232 * if at end of path and rewriting (RENAME and LOCKPARENT), lock target 233 * inode and return info to allow rewrite 234 * if not at end, add name to cache; if at end and neither creating 235 * nor deleting, add name to cache 236 */ 237 int 238 ext2fs_lookup(v) 239 void *v; 240 { 241 struct vop_lookup_args /* { 242 struct vnode *a_dvp; 243 struct vnode **a_vpp; 244 struct componentname *a_cnp; 245 } */ *ap = v; 246 register struct vnode *vdp; /* vnode for directory being searched */ 247 register struct inode *dp; /* inode for directory being searched */ 248 struct buf *bp; /* a buffer of directory entries */ 249 register struct ext2fs_direct *ep; /* the current directory entry */ 250 int entryoffsetinblock; /* offset of ep in bp's buffer */ 251 enum {NONE, COMPACT, FOUND} slotstatus; 252 doff_t slotoffset; /* offset of area with free space */ 253 int slotsize; /* size of area at slotoffset */ 254 int slotfreespace; /* amount of space free in slot */ 255 int slotneeded; /* size of the entry we're seeking */ 256 int numdirpasses; /* strategy for directory search */ 257 doff_t endsearch; /* offset to end directory search */ 258 doff_t prevoff; /* prev entry dp->i_offset */ 259 struct vnode *pdp; /* saved dp during symlink work */ 260 struct vnode *tdp; /* returned by VFS_VGET */ 261 doff_t enduseful; /* pointer past last used dir slot */ 262 u_long bmask; /* block offset mask */ 263 int lockparent; /* 1 => lockparent flag is set */ 264 int wantparent; /* 1 => wantparent or lockparent flag */ 265 int namlen, error; 266 struct vnode **vpp = ap->a_vpp; 267 struct componentname *cnp = ap->a_cnp; 268 struct ucred *cred = cnp->cn_cred; 269 int flags = cnp->cn_flags; 270 int nameiop = cnp->cn_nameiop; 271 272 int dirblksize = VTOI(ap->a_dvp)->i_e2fs->e2fs_bsize; 273 274 bp = NULL; 275 slotoffset = -1; 276 *vpp = NULL; 277 vdp = ap->a_dvp; 278 dp = VTOI(vdp); 279 lockparent = flags & LOCKPARENT; 280 wantparent = flags & (LOCKPARENT|WANTPARENT); 281 /* 282 * Check accessiblity of directory. 283 */ 284 if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0) 285 return (error); 286 287 /* 288 * We now have a segment name to search for, and a directory to search. 289 * 290 * Before tediously performing a linear scan of the directory, 291 * check the name cache to see if the directory/name pair 292 * we are looking for is known already. 293 */ 294 if ((error = cache_lookup(vdp, vpp, cnp)) != 0) { 295 int vpid; /* capability number of vnode */ 296 297 if (error == ENOENT) 298 return (error); 299 /* 300 * Get the next vnode in the path. 301 * See comment below starting `Step through' for 302 * an explaination of the locking protocol. 303 */ 304 pdp = vdp; 305 dp = VTOI(*vpp); 306 vdp = *vpp; 307 vpid = vdp->v_id; 308 if (pdp == vdp) { /* lookup on "." */ 309 VREF(vdp); 310 error = 0; 311 } else if (flags & ISDOTDOT) { 312 VOP_UNLOCK(pdp); 313 error = vget(vdp, 1); 314 if (!error && lockparent && (flags & ISLASTCN)) 315 error = VOP_LOCK(pdp); 316 } else { 317 error = vget(vdp, 1); 318 if (!lockparent || error || !(flags & ISLASTCN)) 319 VOP_UNLOCK(pdp); 320 } 321 /* 322 * Check that the capability number did not change 323 * while we were waiting for the lock. 324 */ 325 if (!error) { 326 if (vpid == vdp->v_id) 327 return (0); 328 vput(vdp); 329 if (lockparent && pdp != vdp && (flags & ISLASTCN)) 330 VOP_UNLOCK(pdp); 331 } 332 if ((error = VOP_LOCK(pdp)) != 0) 333 return (error); 334 vdp = pdp; 335 dp = VTOI(pdp); 336 *vpp = NULL; 337 } 338 339 /* 340 * Suppress search for slots unless creating 341 * file and at end of pathname, in which case 342 * we watch for a place to put the new file in 343 * case it doesn't already exist. 344 */ 345 slotstatus = FOUND; 346 slotfreespace = slotsize = slotneeded = 0; 347 if ((nameiop == CREATE || nameiop == RENAME) && 348 (flags & ISLASTCN)) { 349 slotstatus = NONE; 350 slotneeded = EXT2FS_DIRSIZ(cnp->cn_namelen); 351 } 352 353 /* 354 * If there is cached information on a previous search of 355 * this directory, pick up where we last left off. 356 * We cache only lookups as these are the most common 357 * and have the greatest payoff. Caching CREATE has little 358 * benefit as it usually must search the entire directory 359 * to determine that the entry does not exist. Caching the 360 * location of the last DELETE or RENAME has not reduced 361 * profiling time and hence has been removed in the interest 362 * of simplicity. 363 */ 364 bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; 365 if (nameiop != LOOKUP || dp->i_diroff == 0 || 366 dp->i_diroff > dp->i_e2fs_size) { 367 entryoffsetinblock = 0; 368 dp->i_offset = 0; 369 numdirpasses = 1; 370 } else { 371 dp->i_offset = dp->i_diroff; 372 if ((entryoffsetinblock = dp->i_offset & bmask) && 373 (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))) 374 return (error); 375 numdirpasses = 2; 376 } 377 prevoff = dp->i_offset; 378 endsearch = roundup(dp->i_e2fs_size, dirblksize); 379 enduseful = 0; 380 381 searchloop: 382 while (dp->i_offset < endsearch) { 383 /* 384 * If necessary, get the next directory block. 385 */ 386 if ((dp->i_offset & bmask) == 0) { 387 if (bp != NULL) 388 brelse(bp); 389 error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp); 390 if (error != 0) 391 return (error); 392 entryoffsetinblock = 0; 393 } 394 /* 395 * If still looking for a slot, and at a dirblksize 396 * boundary, have to start looking for free space again. 397 */ 398 if (slotstatus == NONE && 399 (entryoffsetinblock & (dirblksize - 1)) == 0) { 400 slotoffset = -1; 401 slotfreespace = 0; 402 } 403 /* 404 * Get pointer to next entry. 405 * Full validation checks are slow, so we only check 406 * enough to insure forward progress through the 407 * directory. Complete checks can be run by patching 408 * "dirchk" to be true. 409 */ 410 ep = (struct ext2fs_direct *) 411 ((char *)bp->b_data + entryoffsetinblock); 412 if (ep->e2d_reclen == 0 || 413 (dirchk && ext2fs_dirbadentry(vdp, ep, entryoffsetinblock))) { 414 int i; 415 ufs_dirbad(dp, dp->i_offset, "mangled entry"); 416 i = dirblksize - (entryoffsetinblock & (dirblksize - 1)); 417 dp->i_offset += i; 418 entryoffsetinblock += i; 419 continue; 420 } 421 422 /* 423 * If an appropriate sized slot has not yet been found, 424 * check to see if one is available. Also accumulate space 425 * in the current block so that we can determine if 426 * compaction is viable. 427 */ 428 if (slotstatus != FOUND) { 429 int size = ep->e2d_reclen; 430 431 if (ep->e2d_ino != 0) 432 size -= EXT2FS_DIRSIZ(ep->e2d_namlen); 433 if (size > 0) { 434 if (size >= slotneeded) { 435 slotstatus = FOUND; 436 slotoffset = dp->i_offset; 437 slotsize = ep->e2d_reclen; 438 } else if (slotstatus == NONE) { 439 slotfreespace += size; 440 if (slotoffset == -1) 441 slotoffset = dp->i_offset; 442 if (slotfreespace >= slotneeded) { 443 slotstatus = COMPACT; 444 slotsize = dp->i_offset + 445 ep->e2d_reclen - slotoffset; 446 } 447 } 448 } 449 } 450 451 /* 452 * Check for a name match. 453 */ 454 if (ep->e2d_ino) { 455 namlen = ep->e2d_namlen; 456 if (namlen == cnp->cn_namelen && 457 !bcmp(cnp->cn_nameptr, ep->e2d_name, 458 (unsigned)namlen)) { 459 /* 460 * Save directory entry's inode number and 461 * reclen in ndp->ni_ufs area, and release 462 * directory buffer. 463 */ 464 dp->i_ino = ep->e2d_ino; 465 dp->i_reclen = ep->e2d_reclen; 466 brelse(bp); 467 goto found; 468 } 469 } 470 prevoff = dp->i_offset; 471 dp->i_offset += ep->e2d_reclen; 472 entryoffsetinblock += ep->e2d_reclen; 473 if (ep->e2d_ino) 474 enduseful = dp->i_offset; 475 } 476 /* notfound: */ 477 /* 478 * If we started in the middle of the directory and failed 479 * to find our target, we must check the beginning as well. 480 */ 481 if (numdirpasses == 2) { 482 numdirpasses--; 483 dp->i_offset = 0; 484 endsearch = dp->i_diroff; 485 goto searchloop; 486 } 487 if (bp != NULL) 488 brelse(bp); 489 /* 490 * If creating, and at end of pathname and current 491 * directory has not been removed, then can consider 492 * allowing file to be created. 493 */ 494 if ((nameiop == CREATE || nameiop == RENAME) && 495 (flags & ISLASTCN) && dp->i_e2fs_nlink != 0) { 496 /* 497 * Creation of files on a read-only mounted file system 498 * is pointless, so don't proceed any further. 499 */ 500 if (vdp->v_mount->mnt_flag & MNT_RDONLY) 501 return (EROFS); 502 /* 503 * Access for write is interpreted as allowing 504 * creation of files in the directory. 505 */ 506 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0) 507 return (error); 508 /* 509 * Return an indication of where the new directory 510 * entry should be put. If we didn't find a slot, 511 * then set dp->i_count to 0 indicating 512 * that the new slot belongs at the end of the 513 * directory. If we found a slot, then the new entry 514 * can be put in the range from dp->i_offset to 515 * dp->i_offset + dp->i_count. 516 */ 517 if (slotstatus == NONE) { 518 dp->i_offset = roundup(dp->i_e2fs_size, dirblksize); 519 dp->i_count = 0; 520 enduseful = dp->i_offset; 521 } else { 522 dp->i_offset = slotoffset; 523 dp->i_count = slotsize; 524 if (enduseful < slotoffset + slotsize) 525 enduseful = slotoffset + slotsize; 526 } 527 dp->i_endoff = roundup(enduseful, dirblksize); 528 dp->i_flag |= IN_CHANGE | IN_UPDATE; 529 /* 530 * We return with the directory locked, so that 531 * the parameters we set up above will still be 532 * valid if we actually decide to do a direnter(). 533 * We return ni_vp == NULL to indicate that the entry 534 * does not currently exist; we leave a pointer to 535 * the (locked) directory inode in ndp->ni_dvp. 536 * The pathname buffer is saved so that the name 537 * can be obtained later. 538 * 539 * NB - if the directory is unlocked, then this 540 * information cannot be used. 541 */ 542 cnp->cn_flags |= SAVENAME; 543 if (!lockparent) 544 VOP_UNLOCK(vdp); 545 return (EJUSTRETURN); 546 } 547 /* 548 * Insert name into cache (as non-existent) if appropriate. 549 */ 550 if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 551 cache_enter(vdp, *vpp, cnp); 552 return (ENOENT); 553 554 found: 555 /* 556 * Check that directory length properly reflects presence 557 * of this entry. 558 */ 559 if (entryoffsetinblock + EXT2FS_DIRSIZ(ep->e2d_namlen) 560 > dp->i_e2fs_size) { 561 ufs_dirbad(dp, dp->i_offset, "i_size too small"); 562 dp->i_e2fs_size = entryoffsetinblock+EXT2FS_DIRSIZ(ep->e2d_namlen); 563 dp->i_flag |= IN_CHANGE | IN_UPDATE; 564 } 565 566 /* 567 * Found component in pathname. 568 * If the final component of path name, save information 569 * in the cache as to where the entry was found. 570 */ 571 if ((flags & ISLASTCN) && nameiop == LOOKUP) 572 dp->i_diroff = dp->i_offset &~ (dirblksize - 1); 573 574 /* 575 * If deleting, and at end of pathname, return 576 * parameters which can be used to remove file. 577 * If the wantparent flag isn't set, we return only 578 * the directory (in ndp->ni_dvp), otherwise we go 579 * on and lock the inode, being careful with ".". 580 */ 581 if (nameiop == DELETE && (flags & ISLASTCN)) { 582 /* 583 * Write access to directory required to delete files. 584 */ 585 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0) 586 return (error); 587 /* 588 * Return pointer to current entry in dp->i_offset, 589 * and distance past previous entry (if there 590 * is a previous entry in this block) in dp->i_count. 591 * Save directory inode pointer in ndp->ni_dvp for dirremove(). 592 */ 593 if ((dp->i_offset & (dirblksize - 1)) == 0) 594 dp->i_count = 0; 595 else 596 dp->i_count = dp->i_offset - prevoff; 597 if (dp->i_number == dp->i_ino) { 598 VREF(vdp); 599 *vpp = vdp; 600 return (0); 601 } 602 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) 603 return (error); 604 /* 605 * If directory is "sticky", then user must own 606 * the directory, or the file in it, else she 607 * may not delete it (unless she's root). This 608 * implements append-only directories. 609 */ 610 if ((dp->i_e2fs_mode & ISVTX) && 611 cred->cr_uid != 0 && 612 cred->cr_uid != dp->i_e2fs_uid && 613 VTOI(tdp)->i_e2fs_uid != cred->cr_uid) { 614 vput(tdp); 615 return (EPERM); 616 } 617 *vpp = tdp; 618 if (!lockparent) 619 VOP_UNLOCK(vdp); 620 return (0); 621 } 622 623 /* 624 * If rewriting (RENAME), return the inode and the 625 * information required to rewrite the present directory 626 * Must get inode of directory entry to verify it's a 627 * regular file, or empty directory. 628 */ 629 if (nameiop == RENAME && wantparent && 630 (flags & ISLASTCN)) { 631 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0) 632 return (error); 633 /* 634 * Careful about locking second inode. 635 * This can only occur if the target is ".". 636 */ 637 if (dp->i_number == dp->i_ino) 638 return (EISDIR); 639 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) 640 return (error); 641 *vpp = tdp; 642 cnp->cn_flags |= SAVENAME; 643 if (!lockparent) 644 VOP_UNLOCK(vdp); 645 return (0); 646 } 647 648 /* 649 * Step through the translation in the name. We do not `vput' the 650 * directory because we may need it again if a symbolic link 651 * is relative to the current directory. Instead we save it 652 * unlocked as "pdp". We must get the target inode before unlocking 653 * the directory to insure that the inode will not be removed 654 * before we get it. We prevent deadlock by always fetching 655 * inodes from the root, moving down the directory tree. Thus 656 * when following backward pointers ".." we must unlock the 657 * parent directory before getting the requested directory. 658 * There is a potential race condition here if both the current 659 * and parent directories are removed before the VFS_VGET for the 660 * inode associated with ".." returns. We hope that this occurs 661 * infrequently since we cannot avoid this race condition without 662 * implementing a sophisticated deadlock detection algorithm. 663 * Note also that this simple deadlock detection scheme will not 664 * work if the file system has any hard links other than ".." 665 * that point backwards in the directory structure. 666 */ 667 pdp = vdp; 668 if (flags & ISDOTDOT) { 669 VOP_UNLOCK(pdp); /* race to get the inode */ 670 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) { 671 VOP_LOCK(pdp); 672 return (error); 673 } 674 if (lockparent && (flags & ISLASTCN) && 675 (error = VOP_LOCK(pdp)) != 0) { 676 vput(tdp); 677 return (error); 678 } 679 *vpp = tdp; 680 } else if (dp->i_number == dp->i_ino) { 681 VREF(vdp); /* we want ourself, ie "." */ 682 *vpp = vdp; 683 } else { 684 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) 685 return (error); 686 if (!lockparent || !(flags & ISLASTCN)) 687 VOP_UNLOCK(pdp); 688 *vpp = tdp; 689 } 690 691 /* 692 * Insert name into cache if appropriate. 693 */ 694 if (cnp->cn_flags & MAKEENTRY) 695 cache_enter(vdp, *vpp, cnp); 696 return (0); 697 } 698 699 /* 700 * Do consistency checking on a directory entry: 701 * record length must be multiple of 4 702 * entry must fit in rest of its dirblksize block 703 * record must be large enough to contain entry 704 * name is not longer than MAXNAMLEN 705 * name must be as long as advertised, and null terminated 706 */ 707 /* 708 * changed so that it confirms to ext2fs_check_dir_entry 709 */ 710 static int 711 ext2fs_dirbadentry(dp, de, entryoffsetinblock) 712 struct vnode *dp; 713 register struct ext2fs_direct *de; 714 int entryoffsetinblock; 715 { 716 int dirblksize = VTOI(dp)->i_e2fs->e2fs_bsize; 717 718 char * error_msg = NULL; 719 720 if (de->e2d_reclen < EXT2FS_DIRSIZ(1)) /* e2d_namlen = 1 */ 721 error_msg = "rec_len is smaller than minimal"; 722 else if (de->e2d_reclen % 4 != 0) 723 error_msg = "rec_len % 4 != 0"; 724 else if (de->e2d_reclen < EXT2FS_DIRSIZ(de->e2d_namlen)) 725 error_msg = "reclen is too small for name_len"; 726 else if (entryoffsetinblock + de->e2d_reclen > dirblksize) 727 error_msg = "directory entry across blocks"; 728 else if (de->e2d_ino > VTOI(dp)->i_e2fs->e2fs.e2fs_icount) 729 error_msg = "inode out of bounds"; 730 731 if (error_msg != NULL) { 732 printf( "bad directory entry: %s\n" 733 "offset=%d, inode=%lu, rec_len=%d, name_len=%d \n", 734 error_msg, entryoffsetinblock, 735 (unsigned long) de->e2d_ino, de->e2d_reclen, de->e2d_namlen); 736 panic("ext2fs_dirbadentry"); 737 } 738 return error_msg == NULL ? 0 : 1; 739 } 740 741 /* 742 * Write a directory entry after a call to namei, using the parameters 743 * that it left in nameidata. The argument ip is the inode which the new 744 * directory entry will refer to. Dvp is a pointer to the directory to 745 * be written, which was left locked by namei. Remaining parameters 746 * (dp->i_offset, dp->i_count) indicate how the space for the new 747 * entry is to be obtained. 748 */ 749 int 750 ext2fs_direnter(ip, dvp, cnp) 751 struct inode *ip; 752 struct vnode *dvp; 753 register struct componentname *cnp; 754 { 755 register struct ext2fs_direct *ep, *nep; 756 register struct inode *dp; 757 struct buf *bp; 758 struct ext2fs_direct newdir; 759 struct iovec aiov; 760 struct uio auio; 761 u_int dsize; 762 int error, loc, newentrysize, spacefree; 763 char *dirbuf; 764 int dirblksize = ip->i_e2fs->e2fs_bsize; 765 766 767 #ifdef DIAGNOSTIC 768 if ((cnp->cn_flags & SAVENAME) == 0) 769 panic("direnter: missing name"); 770 #endif 771 dp = VTOI(dvp); 772 newdir.e2d_ino = ip->i_number; 773 newdir.e2d_namlen = cnp->cn_namelen; 774 bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1); 775 newentrysize = EXT2FS_DIRSIZ(newdir.e2d_namlen); 776 if (dp->i_count == 0) { 777 /* 778 * If dp->i_count is 0, then namei could find no 779 * space in the directory. Here, dp->i_offset will 780 * be on a directory block boundary and we will write the 781 * new entry into a fresh block. 782 */ 783 if (dp->i_offset & (dirblksize - 1)) 784 panic("ext2fs_direnter: newblk"); 785 auio.uio_offset = dp->i_offset; 786 newdir.e2d_reclen = dirblksize; 787 auio.uio_resid = newentrysize; 788 aiov.iov_len = newentrysize; 789 aiov.iov_base = (caddr_t)&newdir; 790 auio.uio_iov = &aiov; 791 auio.uio_iovcnt = 1; 792 auio.uio_rw = UIO_WRITE; 793 auio.uio_segflg = UIO_SYSSPACE; 794 auio.uio_procp = (struct proc *)0; 795 error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred); 796 if (dirblksize > 797 VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) 798 /* XXX should grow with balloc() */ 799 panic("ext2fs_direnter: frag size"); 800 else if (!error) { 801 dp->i_e2fs_size = roundup(dp->i_e2fs_size, dirblksize); 802 dp->i_flag |= IN_CHANGE; 803 } 804 return (error); 805 } 806 807 /* 808 * If dp->i_count is non-zero, then namei found space 809 * for the new entry in the range dp->i_offset to 810 * dp->i_offset + dp->i_count in the directory. 811 * To use this space, we may have to compact the entries located 812 * there, by copying them together towards the beginning of the 813 * block, leaving the free space in one usable chunk at the end. 814 */ 815 816 /* 817 * Get the block containing the space for the new directory entry. 818 */ 819 if ((error = VOP_BLKATOFF(dvp, (off_t)dp->i_offset, &dirbuf, &bp)) != 0) 820 return (error); 821 /* 822 * Find space for the new entry. In the simple case, the entry at 823 * offset base will have the space. If it does not, then namei 824 * arranged that compacting the region dp->i_offset to 825 * dp->i_offset + dp->i_count would yield the 826 * space. 827 */ 828 ep = (struct ext2fs_direct *)dirbuf; 829 dsize = EXT2FS_DIRSIZ(ep->e2d_namlen); 830 spacefree = ep->e2d_reclen - dsize; 831 for (loc = ep->e2d_reclen; loc < dp->i_count; ) { 832 nep = (struct ext2fs_direct *)(dirbuf + loc); 833 if (ep->e2d_ino) { 834 /* trim the existing slot */ 835 ep->e2d_reclen = dsize; 836 ep = (struct ext2fs_direct *)((char *)ep + dsize); 837 } else { 838 /* overwrite; nothing there; header is ours */ 839 spacefree += dsize; 840 } 841 dsize = EXT2FS_DIRSIZ(nep->e2d_namlen); 842 spacefree += nep->e2d_reclen - dsize; 843 loc += nep->e2d_reclen; 844 bcopy((caddr_t)nep, (caddr_t)ep, dsize); 845 } 846 /* 847 * Update the pointer fields in the previous entry (if any), 848 * copy in the new entry, and write out the block. 849 */ 850 if (ep->e2d_ino == 0) { 851 #ifdef DIAGNOSTIC 852 if (spacefree + dsize < newentrysize) 853 panic("ext2fs_direnter: compact1"); 854 #endif 855 newdir.e2d_reclen = spacefree + dsize; 856 } else { 857 #ifdef DIAGNOSTIC 858 if (spacefree < newentrysize) { 859 printf("ext2fs_direnter: compact2 %u %u", 860 (u_int)spacefree, (u_int)newentrysize); 861 panic("ext2fs_direnter: compact2"); 862 } 863 #endif 864 newdir.e2d_reclen = spacefree; 865 ep->e2d_reclen = dsize; 866 ep = (struct ext2fs_direct *)((char *)ep + dsize); 867 } 868 bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); 869 error = VOP_BWRITE(bp); 870 dp->i_flag |= IN_CHANGE | IN_UPDATE; 871 if (!error && dp->i_endoff && dp->i_endoff < dp->i_e2fs_size) 872 error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, 873 cnp->cn_cred, cnp->cn_proc); 874 return (error); 875 } 876 877 /* 878 * Remove a directory entry after a call to namei, using 879 * the parameters which it left in nameidata. The entry 880 * dp->i_offset contains the offset into the directory of the 881 * entry to be eliminated. The dp->i_count field contains the 882 * size of the previous record in the directory. If this 883 * is 0, the first entry is being deleted, so we need only 884 * zero the inode number to mark the entry as free. If the 885 * entry is not the first in the directory, we must reclaim 886 * the space of the now empty record by adding the record size 887 * to the size of the previous entry. 888 */ 889 int 890 ext2fs_dirremove(dvp, cnp) 891 struct vnode *dvp; 892 struct componentname *cnp; 893 { 894 register struct inode *dp; 895 struct ext2fs_direct *ep; 896 struct buf *bp; 897 int error; 898 899 dp = VTOI(dvp); 900 if (dp->i_count == 0) { 901 /* 902 * First entry in block: set d_ino to zero. 903 */ 904 error = VOP_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp); 905 if (error != 0) 906 return (error); 907 ep->e2d_ino = 0; 908 error = VOP_BWRITE(bp); 909 dp->i_flag |= IN_CHANGE | IN_UPDATE; 910 return (error); 911 } 912 /* 913 * Collapse new free space into previous entry. 914 */ 915 error = VOP_BLKATOFF(dvp, (off_t)(dp->i_offset - dp->i_count), 916 (char **)&ep, &bp); 917 if (error != 0) 918 return (error); 919 ep->e2d_reclen += dp->i_reclen; 920 error = VOP_BWRITE(bp); 921 dp->i_flag |= IN_CHANGE | IN_UPDATE; 922 return (error); 923 } 924 925 /* 926 * Rewrite an existing directory entry to point at the inode 927 * supplied. The parameters describing the directory entry are 928 * set up by a call to namei. 929 */ 930 int 931 ext2fs_dirrewrite(dp, ip, cnp) 932 struct inode *dp, *ip; 933 struct componentname *cnp; 934 { 935 struct buf *bp; 936 struct ext2fs_direct *ep; 937 struct vnode *vdp = ITOV(dp); 938 int error; 939 940 error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp); 941 if (error != 0) 942 return (error); 943 ep->e2d_ino = ip->i_number; 944 error = VOP_BWRITE(bp); 945 dp->i_flag |= IN_CHANGE | IN_UPDATE; 946 return (error); 947 } 948 949 /* 950 * Check if a directory is empty or not. 951 * Inode supplied must be locked. 952 * 953 * Using a struct dirtemplate here is not precisely 954 * what we want, but better than using a struct ext2fs_direct. 955 * 956 * NB: does not handle corrupted directories. 957 */ 958 int 959 ext2fs_dirempty(ip, parentino, cred) 960 register struct inode *ip; 961 ino_t parentino; 962 struct ucred *cred; 963 { 964 register off_t off; 965 struct ext2fs_dirtemplate dbuf; 966 register struct ext2fs_direct *dp = (struct ext2fs_direct *)&dbuf; 967 int error, count, namlen; 968 969 #define MINDIRSIZ (sizeof (struct ext2fs_dirtemplate) / 2) 970 971 for (off = 0; off < ip->i_e2fs_size; off += dp->e2d_reclen) { 972 error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, 973 UIO_SYSSPACE, IO_NODELOCKED, cred, &count, (struct proc *)0); 974 /* 975 * Since we read MINDIRSIZ, residual must 976 * be 0 unless we're at end of file. 977 */ 978 if (error || count != 0) 979 return (0); 980 /* avoid infinite loops */ 981 if (dp->e2d_reclen == 0) 982 return (0); 983 /* skip empty entries */ 984 if (dp->e2d_ino == 0) 985 continue; 986 /* accept only "." and ".." */ 987 namlen = dp->e2d_namlen; 988 if (namlen > 2) 989 return (0); 990 if (dp->e2d_name[0] != '.') 991 return (0); 992 /* 993 * At this point namlen must be 1 or 2. 994 * 1 implies ".", 2 implies ".." if second 995 * char is also "." 996 */ 997 if (namlen == 1) 998 continue; 999 if (dp->e2d_name[1] == '.' && dp->e2d_ino == parentino) 1000 continue; 1001 return (0); 1002 } 1003 return (1); 1004 } 1005 1006 /* 1007 * Check if source directory is in the path of the target directory. 1008 * Target is supplied locked, source is unlocked. 1009 * The target is always vput before returning. 1010 */ 1011 int 1012 ext2fs_checkpath(source, target, cred) 1013 struct inode *source, *target; 1014 struct ucred *cred; 1015 { 1016 struct vnode *vp; 1017 int error, rootino, namlen; 1018 struct ext2fs_dirtemplate dirbuf; 1019 1020 vp = ITOV(target); 1021 if (target->i_number == source->i_number) { 1022 error = EEXIST; 1023 goto out; 1024 } 1025 rootino = ROOTINO; 1026 error = 0; 1027 if (target->i_number == rootino) 1028 goto out; 1029 1030 for (;;) { 1031 if (vp->v_type != VDIR) { 1032 error = ENOTDIR; 1033 break; 1034 } 1035 error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, 1036 sizeof (struct ext2fs_dirtemplate), (off_t)0, UIO_SYSSPACE, 1037 IO_NODELOCKED, cred, (int *)0, (struct proc *)0); 1038 if (error != 0) 1039 break; 1040 namlen = dirbuf.dotdot_namlen; 1041 if (namlen != 2 || 1042 dirbuf.dotdot_name[0] != '.' || 1043 dirbuf.dotdot_name[1] != '.') { 1044 error = ENOTDIR; 1045 break; 1046 } 1047 if (dirbuf.dotdot_ino == source->i_number) { 1048 error = EINVAL; 1049 break; 1050 } 1051 if (dirbuf.dotdot_ino == rootino) 1052 break; 1053 vput(vp); 1054 error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, &vp); 1055 if (error != 0) { 1056 vp = NULL; 1057 break; 1058 } 1059 } 1060 1061 out: 1062 if (error == ENOTDIR) { 1063 printf("checkpath: .. not a directory\n"); 1064 panic("checkpath"); 1065 } 1066 if (vp != NULL) 1067 vput(vp); 1068 return (error); 1069 } 1070 1071