55#include <sys/buf.h> 56#include <sys/mount.h> 57#include <sys/vnode.h> 58#include <sys/malloc.h> 59#include <sys/dirent.h> 60 61#include <ufs/ufs/extattr.h> 62#include <ufs/ufs/quota.h> 63#include <ufs/ufs/inode.h> 64#include <ufs/ufs/dir.h> 65#include <ufs/ufs/ufsmount.h> 66#include <ufs/ufs/ufs_extern.h> 67 68#include <gnu/ext2fs/ext2_extern.h> 69#include <gnu/ext2fs/ext2_fs.h> 70#include <gnu/ext2fs/ext2_fs_sb.h> 71 72/* 73 DIRBLKSIZE in ffs is DEV_BSIZE (in most cases 512) 74 while it is the native blocksize in ext2fs - thus, a #define 75 is no longer appropriate 76*/ 77#undef DIRBLKSIZ 78 79extern int dirchk; 80 81static u_char ext2_ft_to_dt[] = { 82 DT_UNKNOWN, /* EXT2_FT_UNKNOWN */ 83 DT_REG, /* EXT2_FT_REG_FILE */ 84 DT_DIR, /* EXT2_FT_DIR */ 85 DT_CHR, /* EXT2_FT_CHRDEV */ 86 DT_BLK, /* EXT2_FT_BLKDEV */ 87 DT_FIFO, /* EXT2_FT_FIFO */ 88 DT_SOCK, /* EXT2_FT_SOCK */ 89 DT_LNK, /* EXT2_FT_SYMLINK */ 90}; 91#define FTTODT(ft) \ 92 ((ft) > sizeof(ext2_ft_to_dt) / sizeof(ext2_ft_to_dt[0]) ? \ 93 DT_UNKNOWN : ext2_ft_to_dt[(ft)]) 94 95static u_char dt_to_ext2_ft[] = { 96 EXT2_FT_UNKNOWN, /* DT_UNKNOWN */ 97 EXT2_FT_FIFO, /* DT_FIFO */ 98 EXT2_FT_CHRDEV, /* DT_CHR */ 99 EXT2_FT_UNKNOWN, /* unused */ 100 EXT2_FT_DIR, /* DT_DIR */ 101 EXT2_FT_UNKNOWN, /* unused */ 102 EXT2_FT_BLKDEV, /* DT_BLK */ 103 EXT2_FT_UNKNOWN, /* unused */ 104 EXT2_FT_REG_FILE, /* DT_REG */ 105 EXT2_FT_UNKNOWN, /* unused */ 106 EXT2_FT_SYMLINK, /* DT_LNK */ 107 EXT2_FT_UNKNOWN, /* unused */ 108 EXT2_FT_SOCK, /* DT_SOCK */ 109 EXT2_FT_UNKNOWN, /* unused */ 110 EXT2_FT_UNKNOWN, /* DT_WHT */ 111}; 112#define DTTOFT(dt) \ 113 ((dt) > sizeof(dt_to_ext2_ft) / sizeof(dt_to_ext2_ft[0]) ? \ 114 EXT2_FT_UNKNOWN : dt_to_ext2_ft[(dt)]) 115 116static int ext2_dirbadentry __P((struct vnode *dp, 117 struct ext2_dir_entry_2 *de, 118 int entryoffsetinblock)); 119 120/* 121 * Vnode op for reading directories. 122 * 123 * The routine below assumes that the on-disk format of a directory 124 * is the same as that defined by <sys/dirent.h>. If the on-disk 125 * format changes, then it will be necessary to do a conversion 126 * from the on-disk format that read returns to the format defined 127 * by <sys/dirent.h>. 128 */ 129/* 130 * this is exactly what we do here - the problem is that the conversion 131 * will blow up some entries by four bytes, so it can't be done in place. 132 * This is too bad. Right now the conversion is done entry by entry, the 133 * converted entry is sent via uiomove. 134 * 135 * XXX allocate a buffer, convert as many entries as possible, then send 136 * the whole buffer to uiomove 137 */ 138int 139ext2_readdir(ap) 140 struct vop_readdir_args /* { 141 struct vnode *a_vp; 142 struct uio *a_uio; 143 struct ucred *a_cred; 144 } */ *ap; 145{ 146 register struct uio *uio = ap->a_uio; 147 int count, error; 148 149 struct ext2_dir_entry_2 *edp, *dp; 150 int ncookies; 151 struct dirent dstdp; 152 struct uio auio; 153 struct iovec aiov; 154 caddr_t dirbuf; 155 int readcnt; 156 u_quad_t startoffset = uio->uio_offset; 157 158 count = uio->uio_resid; /* legyenek boldogok akik akarnak ... */ 159 uio->uio_resid = count; 160 uio->uio_iov->iov_len = count; 161 162#if 0 163printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", 164 (int)uio->uio_offset, (int)uio->uio_resid, (int)count); 165#endif 166 167 auio = *uio; 168 auio.uio_iov = &aiov; 169 auio.uio_iovcnt = 1; 170 auio.uio_segflg = UIO_SYSSPACE; 171 aiov.iov_len = count; 172 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK); 173 aiov.iov_base = dirbuf; 174 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 175 if (error == 0) { 176 readcnt = count - auio.uio_resid; 177 edp = (struct ext2_dir_entry_2 *)&dirbuf[readcnt]; 178 ncookies = 0; 179 bzero(&dstdp, offsetof(struct dirent, d_name)); 180 for (dp = (struct ext2_dir_entry_2 *)dirbuf; 181 !error && uio->uio_resid > 0 && dp < edp; ) { 182 /*- 183 * "New" ext2fs directory entries differ in 3 ways 184 * from ufs on-disk ones: 185 * - the name is not necessarily NUL-terminated. 186 * - the file type field always exists and always 187 * follows the name length field. 188 * - the file type is encoded in a different way. 189 * 190 * "Old" ext2fs directory entries need no special 191 * conversions, since they binary compatible with 192 * "new" entries having a file type of 0 (i.e., 193 * EXT2_FT_UNKNOWN). Splitting the old name length 194 * field didn't make a mess like it did in ufs, 195 * because ext2fs uses a machine-dependent disk 196 * layout. 197 */ 198 dstdp.d_fileno = dp->inode; 199 dstdp.d_type = FTTODT(dp->file_type); 200 dstdp.d_namlen = dp->name_len; 201 dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); 202 bcopy(dp->name, dstdp.d_name, dstdp.d_namlen); 203 bzero(dstdp.d_name + dstdp.d_namlen, 204 dstdp.d_reclen - offsetof(struct dirent, d_name) - 205 dstdp.d_namlen); 206 207 if (dp->rec_len > 0) { 208 if(dstdp.d_reclen <= uio->uio_resid) { 209 /* advance dp */ 210 dp = (struct ext2_dir_entry_2 *) 211 ((char *)dp + dp->rec_len); 212 error = 213 uiomove((caddr_t)&dstdp, 214 dstdp.d_reclen, uio); 215 if (!error) 216 ncookies++; 217 } else 218 break; 219 } else { 220 error = EIO; 221 break; 222 } 223 } 224 /* we need to correct uio_offset */ 225 uio->uio_offset = startoffset + (caddr_t)dp - dirbuf; 226 227 if (!error && ap->a_ncookies != NULL) { 228 u_long *cookies; 229 u_long *cookiep; 230 off_t off; 231 232 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 233 panic("ext2fs_readdir: unexpected uio from NFS server"); 234 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, 235 M_WAITOK); 236 off = startoffset; 237 for (dp = (struct ext2_dir_entry_2 *)dirbuf, cookiep = cookies; 238 dp < edp; 239 dp = (struct ext2_dir_entry_2 *)((caddr_t) dp + dp->rec_len)) { 240 off += dp->rec_len; 241 *cookiep++ = (u_long) off; 242 } 243 *ap->a_ncookies = ncookies; 244 *ap->a_cookies = cookies; 245 } 246 } 247 FREE(dirbuf, M_TEMP); 248 if (ap->a_eofflag) 249 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; 250 return (error); 251} 252 253/* 254 * Convert a component of a pathname into a pointer to a locked inode. 255 * This is a very central and rather complicated routine. 256 * If the file system is not maintained in a strict tree hierarchy, 257 * this can result in a deadlock situation (see comments in code below). 258 * 259 * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending 260 * on whether the name is to be looked up, created, renamed, or deleted. 261 * When CREATE, RENAME, or DELETE is specified, information usable in 262 * creating, renaming, or deleting a directory entry may be calculated. 263 * If flag has LOCKPARENT or'ed into it and the target of the pathname 264 * exists, lookup returns both the target and its parent directory locked. 265 * When creating or renaming and LOCKPARENT is specified, the target may 266 * not be ".". When deleting and LOCKPARENT is specified, the target may 267 * be "."., but the caller must check to ensure it does an vrele and vput 268 * instead of two vputs. 269 * 270 * Overall outline of ufs_lookup: 271 * 272 * search for name in directory, to found or notfound 273 * notfound: 274 * if creating, return locked directory, leaving info on available slots 275 * else return error 276 * found: 277 * if at end of path and deleting, return information to allow delete 278 * if at end of path and rewriting (RENAME and LOCKPARENT), lock target 279 * inode and return info to allow rewrite 280 * if not at end, add name to cache; if at end and neither creating 281 * nor deleting, add name to cache 282 */ 283int 284ext2_lookup(ap) 285 struct vop_cachedlookup_args /* { 286 struct vnode *a_dvp; 287 struct vnode **a_vpp; 288 struct componentname *a_cnp; 289 } */ *ap; 290{ 291 register struct vnode *vdp; /* vnode for directory being searched */ 292 register struct inode *dp; /* inode for directory being searched */ 293 struct buf *bp; /* a buffer of directory entries */ 294 register struct ext2_dir_entry_2 *ep; /* the current directory entry */ 295 int entryoffsetinblock; /* offset of ep in bp's buffer */ 296 enum {NONE, COMPACT, FOUND} slotstatus; 297 doff_t slotoffset; /* offset of area with free space */ 298 int slotsize; /* size of area at slotoffset */ 299 int slotfreespace; /* amount of space free in slot */ 300 int slotneeded; /* size of the entry we're seeking */ 301 int numdirpasses; /* strategy for directory search */ 302 doff_t endsearch; /* offset to end directory search */ 303 doff_t prevoff; /* prev entry dp->i_offset */ 304 struct vnode *pdp; /* saved dp during symlink work */ 305 struct vnode *tdp; /* returned by VFS_VGET */ 306 doff_t enduseful; /* pointer past last used dir slot */ 307 u_long bmask; /* block offset mask */ 308 int lockparent; /* 1 => lockparent flag is set */ 309 int wantparent; /* 1 => wantparent or lockparent flag */ 310 int namlen, error; 311 struct vnode **vpp = ap->a_vpp; 312 struct componentname *cnp = ap->a_cnp; 313 struct ucred *cred = cnp->cn_cred; 314 int flags = cnp->cn_flags; 315 int nameiop = cnp->cn_nameiop; 316 struct proc *p = cnp->cn_proc; 317 318 int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize; 319 320 bp = NULL; 321 slotoffset = -1; 322 *vpp = NULL; 323 vdp = ap->a_dvp; 324 dp = VTOI(vdp); 325 lockparent = flags & LOCKPARENT; 326 wantparent = flags & (LOCKPARENT|WANTPARENT); 327 328 /* 329 * We now have a segment name to search for, and a directory to search. 330 */ 331 332 /* 333 * Suppress search for slots unless creating 334 * file and at end of pathname, in which case 335 * we watch for a place to put the new file in 336 * case it doesn't already exist. 337 */ 338 slotstatus = FOUND; 339 slotfreespace = slotsize = slotneeded = 0; 340 if ((nameiop == CREATE || nameiop == RENAME) && 341 (flags & ISLASTCN)) { 342 slotstatus = NONE; 343 slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen); 344 /* was 345 slotneeded = (sizeof(struct direct) - MAXNAMLEN + 346 cnp->cn_namelen + 3) &~ 3; */ 347 } 348 349 /* 350 * If there is cached information on a previous search of 351 * this directory, pick up where we last left off. 352 * We cache only lookups as these are the most common 353 * and have the greatest payoff. Caching CREATE has little 354 * benefit as it usually must search the entire directory 355 * to determine that the entry does not exist. Caching the 356 * location of the last DELETE or RENAME has not reduced 357 * profiling time and hence has been removed in the interest 358 * of simplicity. 359 */ 360 bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; 361 if (nameiop != LOOKUP || dp->i_diroff == 0 || 362 dp->i_diroff > dp->i_size) { 363 entryoffsetinblock = 0; 364 dp->i_offset = 0; 365 numdirpasses = 1; 366 } else { 367 dp->i_offset = dp->i_diroff; 368 if ((entryoffsetinblock = dp->i_offset & bmask) && 369 (error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))) 370 return (error); 371 numdirpasses = 2; 372 nchstats.ncs_2passes++; 373 } 374 prevoff = dp->i_offset; 375 endsearch = roundup(dp->i_size, DIRBLKSIZ); 376 enduseful = 0; 377 378searchloop: 379 while (dp->i_offset < endsearch) { 380 /* 381 * If necessary, get the next directory block. 382 */ 383 if ((dp->i_offset & bmask) == 0) { 384 if (bp != NULL) 385 brelse(bp); 386 if ((error = 387 UFS_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)) != 0) 388 return (error); 389 entryoffsetinblock = 0; 390 } 391 /* 392 * If still looking for a slot, and at a DIRBLKSIZE 393 * boundary, have to start looking for free space again. 394 */ 395 if (slotstatus == NONE && 396 (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) { 397 slotoffset = -1; 398 slotfreespace = 0; 399 } 400 /* 401 * Get pointer to next entry. 402 * Full validation checks are slow, so we only check 403 * enough to insure forward progress through the 404 * directory. Complete checks can be run by patching 405 * "dirchk" to be true. 406 */ 407 ep = (struct ext2_dir_entry_2 *) 408 ((char *)bp->b_data + entryoffsetinblock); 409 if (ep->rec_len == 0 || 410 (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) { 411 int i; 412 ufs_dirbad(dp, dp->i_offset, "mangled entry"); 413 i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); 414 dp->i_offset += i; 415 entryoffsetinblock += i; 416 continue; 417 } 418 419 /* 420 * If an appropriate sized slot has not yet been found, 421 * check to see if one is available. Also accumulate space 422 * in the current block so that we can determine if 423 * compaction is viable. 424 */ 425 if (slotstatus != FOUND) { 426 int size = ep->rec_len; 427 428 if (ep->inode != 0) 429 size -= EXT2_DIR_REC_LEN(ep->name_len); 430 if (size > 0) { 431 if (size >= slotneeded) { 432 slotstatus = FOUND; 433 slotoffset = dp->i_offset; 434 slotsize = ep->rec_len; 435 } else if (slotstatus == NONE) { 436 slotfreespace += size; 437 if (slotoffset == -1) 438 slotoffset = dp->i_offset; 439 if (slotfreespace >= slotneeded) { 440 slotstatus = COMPACT; 441 slotsize = dp->i_offset + 442 ep->rec_len - slotoffset; 443 } 444 } 445 } 446 } 447 448 /* 449 * Check for a name match. 450 */ 451 if (ep->inode) { 452 namlen = ep->name_len; 453 if (namlen == cnp->cn_namelen && 454 !bcmp(cnp->cn_nameptr, ep->name, 455 (unsigned)namlen)) { 456 /* 457 * Save directory entry's inode number and 458 * reclen in ndp->ni_ufs area, and release 459 * directory buffer. 460 */ 461 dp->i_ino = ep->inode; 462 dp->i_reclen = ep->rec_len; 463 brelse(bp); 464 goto found; 465 } 466 } 467 prevoff = dp->i_offset; 468 dp->i_offset += ep->rec_len; 469 entryoffsetinblock += ep->rec_len; 470 if (ep->inode) 471 enduseful = dp->i_offset; 472 } 473/* notfound: */ 474 /* 475 * If we started in the middle of the directory and failed 476 * to find our target, we must check the beginning as well. 477 */ 478 if (numdirpasses == 2) { 479 numdirpasses--; 480 dp->i_offset = 0; 481 endsearch = dp->i_diroff; 482 goto searchloop; 483 } 484 if (bp != NULL) 485 brelse(bp); 486 /* 487 * If creating, and at end of pathname and current 488 * directory has not been removed, then can consider 489 * allowing file to be created. 490 */ 491 if ((nameiop == CREATE || nameiop == RENAME) && 492 (flags & ISLASTCN) && dp->i_nlink != 0) { 493 /* 494 * Access for write is interpreted as allowing 495 * creation of files in the directory. 496 */ 497 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0) 498 return (error); 499 /* 500 * Return an indication of where the new directory 501 * entry should be put. If we didn't find a slot, 502 * then set dp->i_count to 0 indicating 503 * that the new slot belongs at the end of the 504 * directory. If we found a slot, then the new entry 505 * can be put in the range from dp->i_offset to 506 * dp->i_offset + dp->i_count. 507 */ 508 if (slotstatus == NONE) { 509 dp->i_offset = roundup(dp->i_size, DIRBLKSIZ); 510 dp->i_count = 0; 511 enduseful = dp->i_offset; 512 } else { 513 dp->i_offset = slotoffset; 514 dp->i_count = slotsize; 515 if (enduseful < slotoffset + slotsize) 516 enduseful = slotoffset + slotsize; 517 } 518 dp->i_endoff = roundup(enduseful, DIRBLKSIZ); 519 dp->i_flag |= IN_CHANGE | IN_UPDATE; 520 /* 521 * We return with the directory locked, so that 522 * the parameters we set up above will still be 523 * valid if we actually decide to do a direnter(). 524 * We return ni_vp == NULL to indicate that the entry 525 * does not currently exist; we leave a pointer to 526 * the (locked) directory inode in ndp->ni_dvp. 527 * The pathname buffer is saved so that the name 528 * can be obtained later. 529 * 530 * NB - if the directory is unlocked, then this 531 * information cannot be used. 532 */ 533 cnp->cn_flags |= SAVENAME; 534 if (!lockparent) 535 VOP_UNLOCK(vdp, 0, p); 536 return (EJUSTRETURN); 537 } 538 /* 539 * Insert name into cache (as non-existent) if appropriate. 540 */ 541 if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 542 cache_enter(vdp, *vpp, cnp); 543 return (ENOENT); 544 545found: 546 if (numdirpasses == 2) 547 nchstats.ncs_pass2++; 548 /* 549 * Check that directory length properly reflects presence 550 * of this entry. 551 */ 552 if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->name_len) 553 > dp->i_size) { 554 ufs_dirbad(dp, dp->i_offset, "i_size too small"); 555 dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->name_len); 556 dp->i_flag |= IN_CHANGE | IN_UPDATE; 557 } 558 559 /* 560 * Found component in pathname. 561 * If the final component of path name, save information 562 * in the cache as to where the entry was found. 563 */ 564 if ((flags & ISLASTCN) && nameiop == LOOKUP) 565 dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1); 566 567 /* 568 * If deleting, and at end of pathname, return 569 * parameters which can be used to remove file. 570 * If the wantparent flag isn't set, we return only 571 * the directory (in ndp->ni_dvp), otherwise we go 572 * on and lock the inode, being careful with ".". 573 */ 574 if (nameiop == DELETE && (flags & ISLASTCN)) { 575 /* 576 * Write access to directory required to delete files. 577 */ 578 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0) 579 return (error); 580 /* 581 * Return pointer to current entry in dp->i_offset, 582 * and distance past previous entry (if there 583 * is a previous entry in this block) in dp->i_count. 584 * Save directory inode pointer in ndp->ni_dvp for dirremove(). 585 */ 586 if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) 587 dp->i_count = 0; 588 else 589 dp->i_count = dp->i_offset - prevoff; 590 if (dp->i_number == dp->i_ino) { 591 VREF(vdp); 592 *vpp = vdp; 593 return (0); 594 } 595 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) 596 return (error); 597 /* 598 * If directory is "sticky", then user must own 599 * the directory, or the file in it, else she 600 * may not delete it (unless she's root). This 601 * implements append-only directories. 602 */ 603 if ((dp->i_mode & ISVTX) && 604 cred->cr_uid != 0 && 605 cred->cr_uid != dp->i_uid && 606 VTOI(tdp)->i_uid != cred->cr_uid) { 607 vput(tdp); 608 return (EPERM); 609 } 610 *vpp = tdp; 611 if (!lockparent) 612 VOP_UNLOCK(vdp, 0, p); 613 return (0); 614 } 615 616 /* 617 * If rewriting (RENAME), return the inode and the 618 * information required to rewrite the present directory 619 * Must get inode of directory entry to verify it's a 620 * regular file, or empty directory. 621 */ 622 if (nameiop == RENAME && wantparent && 623 (flags & ISLASTCN)) { 624 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0) 625 return (error); 626 /* 627 * Careful about locking second inode. 628 * This can only occur if the target is ".". 629 */ 630 if (dp->i_number == dp->i_ino) 631 return (EISDIR); 632 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) 633 return (error); 634 *vpp = tdp; 635 cnp->cn_flags |= SAVENAME; 636 if (!lockparent) 637 VOP_UNLOCK(vdp, 0, p); 638 return (0); 639 } 640 641 /* 642 * Step through the translation in the name. We do not `vput' the 643 * directory because we may need it again if a symbolic link 644 * is relative to the current directory. Instead we save it 645 * unlocked as "pdp". We must get the target inode before unlocking 646 * the directory to insure that the inode will not be removed 647 * before we get it. We prevent deadlock by always fetching 648 * inodes from the root, moving down the directory tree. Thus 649 * when following backward pointers ".." we must unlock the 650 * parent directory before getting the requested directory. 651 * There is a potential race condition here if both the current 652 * and parent directories are removed before the VFS_VGET for the 653 * inode associated with ".." returns. We hope that this occurs 654 * infrequently since we cannot avoid this race condition without 655 * implementing a sophisticated deadlock detection algorithm. 656 * Note also that this simple deadlock detection scheme will not 657 * work if the file system has any hard links other than ".." 658 * that point backwards in the directory structure. 659 */ 660 pdp = vdp; 661 if (flags & ISDOTDOT) { 662 VOP_UNLOCK(pdp, 0, p); /* race to get the inode */ 663 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) { 664 vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p); 665 return (error); 666 } 667 if (lockparent && (flags & ISLASTCN) && 668 (error = vn_lock(pdp, LK_EXCLUSIVE, p))) { 669 vput(tdp); 670 return (error); 671 } 672 *vpp = tdp; 673 } else if (dp->i_number == dp->i_ino) { 674 VREF(vdp); /* we want ourself, ie "." */ 675 *vpp = vdp; 676 } else { 677 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) 678 return (error); 679 if (!lockparent || !(flags & ISLASTCN)) 680 VOP_UNLOCK(pdp, 0, p); 681 *vpp = tdp; 682 } 683 684 /* 685 * Insert name into cache if appropriate. 686 */ 687 if (cnp->cn_flags & MAKEENTRY) 688 cache_enter(vdp, *vpp, cnp); 689 return (0); 690} 691 692/* 693 * Do consistency checking on a directory entry: 694 * record length must be multiple of 4 695 * entry must fit in rest of its DIRBLKSIZ block 696 * record must be large enough to contain entry 697 * name is not longer than MAXNAMLEN 698 * name must be as long as advertised, and null terminated 699 */ 700/* 701 * changed so that it confirms to ext2_check_dir_entry 702 */ 703static int 704ext2_dirbadentry(dp, de, entryoffsetinblock) 705 struct vnode *dp; 706 register struct ext2_dir_entry_2 *de; 707 int entryoffsetinblock; 708{ 709 int DIRBLKSIZ = VTOI(dp)->i_e2fs->s_blocksize; 710 711 char * error_msg = NULL; 712 713 if (de->rec_len < EXT2_DIR_REC_LEN(1)) 714 error_msg = "rec_len is smaller than minimal"; 715 else if (de->rec_len % 4 != 0) 716 error_msg = "rec_len % 4 != 0"; 717 else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len)) 718 error_msg = "reclen is too small for name_len"; 719 else if (entryoffsetinblock + de->rec_len > DIRBLKSIZ) 720 error_msg = "directory entry across blocks"; 721 /* else LATER 722 if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count) 723 error_msg = "inode out of bounds"; 724 */ 725 726 if (error_msg != NULL) { 727 printf("bad directory entry: %s\n", error_msg); 728 printf("offset=%d, inode=%lu, rec_len=%u, name_len=%u\n", 729 entryoffsetinblock, (unsigned long)de->inode, 730 de->rec_len, de->name_len); 731 } 732 return error_msg == NULL ? 0 : 1; 733} 734 735/* 736 * Write a directory entry after a call to namei, using the parameters 737 * that it left in nameidata. The argument ip is the inode which the new 738 * directory entry will refer to. Dvp is a pointer to the directory to 739 * be written, which was left locked by namei. Remaining parameters 740 * (dp->i_offset, dp->i_count) indicate how the space for the new 741 * entry is to be obtained. 742 */ 743int 744ext2_direnter(ip, dvp, cnp) 745 struct inode *ip; 746 struct vnode *dvp; 747 register struct componentname *cnp; 748{ 749 register struct ext2_dir_entry_2 *ep, *nep; 750 register struct inode *dp; 751 struct buf *bp; 752 struct ext2_dir_entry_2 newdir; 753 struct iovec aiov; 754 struct uio auio; 755 u_int dsize; 756 int error, loc, newentrysize, spacefree; 757 char *dirbuf; 758 int DIRBLKSIZ = ip->i_e2fs->s_blocksize; 759 760 761#if DIAGNOSTIC 762 if ((cnp->cn_flags & SAVENAME) == 0) 763 panic("direnter: missing name"); 764#endif 765 dp = VTOI(dvp); 766 newdir.inode = ip->i_number; 767 newdir.name_len = cnp->cn_namelen; 768 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, 769 EXT2_FEATURE_INCOMPAT_FILETYPE)) 770 newdir.file_type = DTTOFT(IFTODT(ip->i_mode)); 771 else 772 newdir.file_type = EXT2_FT_UNKNOWN; 773 bcopy(cnp->cn_nameptr, newdir.name, (unsigned)cnp->cn_namelen + 1); 774 newentrysize = EXT2_DIR_REC_LEN(newdir.name_len); 775 if (dp->i_count == 0) { 776 /* 777 * If dp->i_count is 0, then namei could find no 778 * space in the directory. Here, dp->i_offset will 779 * be on a directory block boundary and we will write the 780 * new entry into a fresh block. 781 */ 782 if (dp->i_offset & (DIRBLKSIZ - 1)) 783 panic("ext2_direnter: newblk"); 784 auio.uio_offset = dp->i_offset; 785 newdir.rec_len = DIRBLKSIZ; 786 auio.uio_resid = newentrysize; 787 aiov.iov_len = newentrysize; 788 aiov.iov_base = (caddr_t)&newdir; 789 auio.uio_iov = &aiov; 790 auio.uio_iovcnt = 1; 791 auio.uio_rw = UIO_WRITE; 792 auio.uio_segflg = UIO_SYSSPACE; 793 auio.uio_procp = (struct proc *)0; 794 error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred); 795 if (DIRBLKSIZ > 796 VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) 797 /* XXX should grow with balloc() */ 798 panic("ext2_direnter: frag size"); 799 else if (!error) { 800 dp->i_size = roundup(dp->i_size, DIRBLKSIZ); 801 dp->i_flag |= IN_CHANGE; 802 } 803 return (error); 804 } 805 806 /* 807 * If dp->i_count is non-zero, then namei found space 808 * for the new entry in the range dp->i_offset to 809 * dp->i_offset + dp->i_count in the directory. 810 * To use this space, we may have to compact the entries located 811 * there, by copying them together towards the beginning of the 812 * block, leaving the free space in one usable chunk at the end. 813 */ 814 815 /* 816 * Increase size of directory if entry eats into new space. 817 * This should never push the size past a new multiple of 818 * DIRBLKSIZE. 819 * 820 * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. 821 */ 822 if (dp->i_offset + dp->i_count > dp->i_size) 823 dp->i_size = dp->i_offset + dp->i_count; 824 /* 825 * Get the block containing the space for the new directory entry. 826 */ 827 if ((error = UFS_BLKATOFF(dvp, (off_t)dp->i_offset, &dirbuf, &bp)) != 0) 828 return (error); 829 /* 830 * Find space for the new entry. In the simple case, the entry at 831 * offset base will have the space. If it does not, then namei 832 * arranged that compacting the region dp->i_offset to 833 * dp->i_offset + dp->i_count would yield the 834 * space. 835 */ 836 ep = (struct ext2_dir_entry_2 *)dirbuf; 837 dsize = EXT2_DIR_REC_LEN(ep->name_len); 838 spacefree = ep->rec_len - dsize; 839 for (loc = ep->rec_len; loc < dp->i_count; ) { 840 nep = (struct ext2_dir_entry_2 *)(dirbuf + loc); 841 if (ep->inode) { 842 /* trim the existing slot */ 843 ep->rec_len = dsize; 844 ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); 845 } else { 846 /* overwrite; nothing there; header is ours */ 847 spacefree += dsize; 848 } 849 dsize = EXT2_DIR_REC_LEN(nep->name_len); 850 spacefree += nep->rec_len - dsize; 851 loc += nep->rec_len; 852 bcopy((caddr_t)nep, (caddr_t)ep, dsize); 853 } 854 /* 855 * Update the pointer fields in the previous entry (if any), 856 * copy in the new entry, and write out the block. 857 */ 858 if (ep->inode == 0) { 859 if (spacefree + dsize < newentrysize) 860 panic("ext2_direnter: compact1"); 861 newdir.rec_len = spacefree + dsize; 862 } else { 863 if (spacefree < newentrysize) 864 panic("ext2_direnter: compact2"); 865 newdir.rec_len = spacefree; 866 ep->rec_len = dsize; 867 ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); 868 } 869 bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); 870 error = BUF_WRITE(bp); 871 dp->i_flag |= IN_CHANGE | IN_UPDATE; 872 if (!error && dp->i_endoff && dp->i_endoff < dp->i_size) 873 error = UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, 874 cnp->cn_cred, cnp->cn_proc); 875 return (error); 876} 877 878/* 879 * Remove a directory entry after a call to namei, using 880 * the parameters which it left in nameidata. The entry 881 * dp->i_offset contains the offset into the directory of the 882 * entry to be eliminated. The dp->i_count field contains the 883 * size of the previous record in the directory. If this 884 * is 0, the first entry is being deleted, so we need only 885 * zero the inode number to mark the entry as free. If the 886 * entry is not the first in the directory, we must reclaim 887 * the space of the now empty record by adding the record size 888 * to the size of the previous entry. 889 */ 890int 891ext2_dirremove(dvp, cnp) 892 struct vnode *dvp; 893 struct componentname *cnp; 894{ 895 register struct inode *dp; 896 struct ext2_dir_entry_2 *ep; 897 struct buf *bp; 898 int error; 899 900 dp = VTOI(dvp); 901 if (dp->i_count == 0) { 902 /* 903 * First entry in block: set d_ino to zero. 904 */ 905 if ((error = 906 UFS_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) 907 return (error); 908 ep->inode = 0; 909 error = BUF_WRITE(bp); 910 dp->i_flag |= IN_CHANGE | IN_UPDATE; 911 return (error); 912 } 913 /* 914 * Collapse new free space into previous entry. 915 */ 916 if ((error = UFS_BLKATOFF(dvp, (off_t)(dp->i_offset - dp->i_count), 917 (char **)&ep, &bp)) != 0) 918 return (error); 919 ep->rec_len += dp->i_reclen; 920 error = BUF_WRITE(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 */ 930int 931ext2_dirrewrite(dp, ip, cnp) 932 struct inode *dp, *ip; 933 struct componentname *cnp; 934{ 935 struct buf *bp; 936 struct ext2_dir_entry_2 *ep; 937 struct vnode *vdp = ITOV(dp); 938 int error; 939 940 if ((error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) 941 return (error); 942 ep->inode = ip->i_number; 943 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, 944 EXT2_FEATURE_INCOMPAT_FILETYPE)) 945 ep->file_type = DTTOFT(IFTODT(ip->i_mode)); 946 else 947 ep->file_type = EXT2_FT_UNKNOWN; 948 error = BUF_WRITE(bp); 949 dp->i_flag |= IN_CHANGE | IN_UPDATE; 950 return (error); 951} 952 953/* 954 * Check if a directory is empty or not. 955 * Inode supplied must be locked. 956 * 957 * Using a struct dirtemplate here is not precisely 958 * what we want, but better than using a struct direct. 959 * 960 * NB: does not handle corrupted directories. 961 */ 962int 963ext2_dirempty(ip, parentino, cred) 964 register struct inode *ip; 965 ino_t parentino; 966 struct ucred *cred; 967{ 968 register off_t off; 969 struct dirtemplate dbuf; 970 register struct ext2_dir_entry_2 *dp = (struct ext2_dir_entry_2 *)&dbuf; 971 int error, count, namlen; 972 973#define MINDIRSIZ (sizeof (struct dirtemplate) / 2) 974 975 for (off = 0; off < ip->i_size; off += dp->rec_len) { 976 error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, 977 UIO_SYSSPACE, IO_NODELOCKED, cred, &count, (struct proc *)0); 978 /* 979 * Since we read MINDIRSIZ, residual must 980 * be 0 unless we're at end of file. 981 */ 982 if (error || count != 0) 983 return (0); 984 /* avoid infinite loops */ 985 if (dp->rec_len == 0) 986 return (0); 987 /* skip empty entries */ 988 if (dp->inode == 0) 989 continue; 990 /* accept only "." and ".." */ 991 namlen = dp->name_len; 992 if (namlen > 2) 993 return (0); 994 if (dp->name[0] != '.') 995 return (0); 996 /* 997 * At this point namlen must be 1 or 2. 998 * 1 implies ".", 2 implies ".." if second 999 * char is also "." 1000 */ 1001 if (namlen == 1) 1002 continue; 1003 if (dp->name[1] == '.' && dp->inode == parentino) 1004 continue; 1005 return (0); 1006 } 1007 return (1); 1008} 1009 1010/* 1011 * Check if source directory is in the path of the target directory. 1012 * Target is supplied locked, source is unlocked. 1013 * The target is always vput before returning. 1014 */ 1015int 1016ext2_checkpath(source, target, cred) 1017 struct inode *source, *target; 1018 struct ucred *cred; 1019{ 1020 struct vnode *vp; 1021 int error, rootino, namlen; 1022 struct dirtemplate dirbuf; 1023 1024 vp = ITOV(target); 1025 if (target->i_number == source->i_number) { 1026 error = EEXIST; 1027 goto out; 1028 } 1029 rootino = ROOTINO; 1030 error = 0; 1031 if (target->i_number == rootino) 1032 goto out; 1033 1034 for (;;) { 1035 if (vp->v_type != VDIR) { 1036 error = ENOTDIR; 1037 break; 1038 } 1039 error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, 1040 sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, 1041 IO_NODELOCKED, cred, (int *)0, (struct proc *)0); 1042 if (error != 0) 1043 break; 1044 namlen = dirbuf.dotdot_type; /* like ufs little-endian */ 1045 if (namlen != 2 || 1046 dirbuf.dotdot_name[0] != '.' || 1047 dirbuf.dotdot_name[1] != '.') { 1048 error = ENOTDIR; 1049 break; 1050 } 1051 if (dirbuf.dotdot_ino == source->i_number) { 1052 error = EINVAL; 1053 break; 1054 } 1055 if (dirbuf.dotdot_ino == rootino) 1056 break; 1057 vput(vp); 1058 if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, &vp)) != 0) { 1059 vp = NULL; 1060 break; 1061 } 1062 } 1063 1064out: 1065 if (error == ENOTDIR) 1066 printf("checkpath: .. not a directory\n"); 1067 if (vp != NULL) 1068 vput(vp); 1069 return (error); 1070} 1071
|