1/* $FreeBSD: head/sys/fs/msdosfs/msdosfs_lookup.c 204474 2010-02-28 17:17:29Z kib $ */ |
2/* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */ 3 4/*- 5 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 6 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 7 * All rights reserved. 8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 9 * --- 46 unchanged lines hidden (view full) --- 56#include <sys/vnode.h> 57 58#include <fs/msdosfs/bpb.h> 59#include <fs/msdosfs/direntry.h> 60#include <fs/msdosfs/denode.h> 61#include <fs/msdosfs/fat.h> 62#include <fs/msdosfs/msdosfsmount.h> 63 |
64static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, 65 struct componentname *cnp, u_int64_t *inum); 66static int msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff, 67 struct vnode **rvp); 68 69int 70msdosfs_lookup(struct vop_cachedlookup_args *ap) 71{ 72 73 return (msdosfs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); 74} 75 |
76/* 77 * When we search a directory the blocks containing directory entries are 78 * read and examined. The directory entries contain information that would 79 * normally be in the inode of a unix filesystem. This means that some of 80 * a directory's contents may also be in memory resident denodes (sort of 81 * an inode). This can cause problems if we are searching while some other 82 * process is modifying a directory. To prevent one process from accessing 83 * incompletely modified directory information we depend upon being the 84 * sole owner of a directory block. bread/brelse provide this service. 85 * This being the case, when a process modifies a directory it must first 86 * acquire the disk block that contains the directory entry to be modified. 87 * Then update the disk block and the denode, and then write the disk block 88 * out to disk. This way disk blocks containing directory entries and in 89 * memory denode's will be in synch. 90 */ |
91static int 92msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, 93 struct componentname *cnp, u_int64_t *dd_inum) |
94{ 95 struct mbnambuf nb; |
96 daddr_t bn; 97 int error; 98 int slotcount; 99 int slotoffset = 0; 100 int frcn; 101 u_long cluster; 102 int blkoff; 103 int diroff; --- 5 unchanged lines hidden (view full) --- 109 struct denode *tdp; 110 struct msdosfsmount *pmp; 111 struct buf *bp = 0; 112 struct direntry *dep = NULL; 113 u_char dosfilename[12]; 114 int flags = cnp->cn_flags; 115 int nameiop = cnp->cn_nameiop; 116 int unlen; |
117 u_int64_t inode1; |
118 119 int wincnt = 1; 120 int chksum = -1, chksum_ok; 121 int olddos = 1; 122 123#ifdef MSDOSFS_DEBUG 124 printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr); 125#endif 126 dp = VTODE(vdp); 127 pmp = dp->de_pmp; |
128 if (vpp != NULL) 129 *vpp = NULL; |
130#ifdef MSDOSFS_DEBUG 131 printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n", 132 vdp, dp, dp->de_Attributes); 133#endif 134 |
135 restart: |
136 /* 137 * If they are going after the . or .. entry in the root directory, 138 * they won't find it. DOS filesystems don't have them in the root 139 * directory. So, we fake it. deget() is in on this scam too. 140 */ 141 if ((vdp->v_vflag & VV_ROOT) && cnp->cn_nameptr[0] == '.' && 142 (cnp->cn_namelen == 1 || 143 (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) { --- 295 unchanged lines hidden (view full) --- 439 /* 440 * If we entered at foundroot, then we are looking for the . or .. 441 * entry of the filesystems root directory. isadir and scn were 442 * setup before jumping here. And, bp is already null. 443 */ 444 if (FAT32(pmp) && scn == MSDOSFSROOT) 445 scn = pmp->pm_rootdirblk; 446 |
447 if (dd_inum != NULL) { 448 *dd_inum = (uint64_t)pmp->pm_bpcluster * scn + blkoff; 449 return (0); 450 } 451 |
452 /* 453 * If deleting, and at end of pathname, return 454 * parameters which can be used to remove file. 455 */ 456 if (nameiop == DELETE && (flags & ISLASTCN)) { 457 /* 458 * Don't allow deleting the root. 459 */ --- 56 unchanged lines hidden (view full) --- 516 * directory because we may need it again if a symbolic link 517 * is relative to the current directory. Instead we save it 518 * unlocked as "pdp". We must get the target inode before unlocking 519 * the directory to insure that the inode will not be removed 520 * before we get it. We prevent deadlock by always fetching 521 * inodes from the root, moving down the directory tree. Thus 522 * when following backward pointers ".." we must unlock the 523 * parent directory before getting the requested directory. |
524 */ 525 pdp = vdp; 526 if (flags & ISDOTDOT) { |
527 error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp); |
528 if (error) 529 return (error); |
530 /* 531 * Recheck that ".." still points to the inode we 532 * looked up before pdp lock was dropped. 533 */ 534 error = msdosfs_lookup_(pdp, NULL, cnp, &inode1); 535 if (error) { 536 vput(*vpp); 537 return (error); 538 } 539 if (VTODE(*vpp)->de_inode != inode1) { 540 vput(*vpp); 541 goto restart; 542 } |
543 } else if (dp->de_StartCluster == scn && isadir) { 544 VREF(vdp); /* we want ourself, ie "." */ 545 *vpp = vdp; 546 } else { 547 if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) 548 return (error); 549 *vpp = DETOV(tdp); 550 } 551 552 /* 553 * Insert name into cache if appropriate. 554 */ 555 if (cnp->cn_flags & MAKEENTRY) 556 cache_enter(vdp, *vpp, cnp); 557 return (0); 558} 559 |
560static int 561msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff, 562 struct vnode **rvp) 563{ 564 struct mount *mp; 565 struct msdosfsmount *pmp; 566 struct denode *rdp; 567 int ltype, error; 568 569 mp = vp->v_mount; 570 pmp = VFSTOMSDOSFS(mp); 571 ltype = VOP_ISLOCKED(vp); 572 KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED, 573 ("msdosfs_deget_dotdot: vp not locked")); 574 575 error = vfs_busy(mp, MBF_NOWAIT); 576 if (error != 0) { 577 vfs_ref(mp); 578 VOP_UNLOCK(vp, 0); 579 error = vfs_busy(mp, 0); 580 vn_lock(vp, ltype | LK_RETRY); 581 vfs_rel(mp); 582 if (error != 0) 583 return (ENOENT); 584 if (vp->v_iflag & VI_DOOMED) { 585 vfs_unbusy(mp); 586 return (ENOENT); 587 } 588 } 589 VOP_UNLOCK(vp, 0); 590 error = deget(pmp, cluster, blkoff, &rdp); 591 vfs_unbusy(mp); 592 if (error == 0) 593 *rvp = DETOV(rdp); 594 vn_lock(vp, ltype | LK_RETRY); 595 if (vp->v_iflag & VI_DOOMED) { 596 if (error == 0) 597 vput(*rvp); 598 error = ENOENT; 599 } 600 return (error); 601} 602 |
603/* 604 * dep - directory entry to copy into the directory 605 * ddep - directory to add to 606 * depp - return the address of the denode for the created directory entry 607 * if depp != 0 608 * cnp - componentname needed for Win95 long filenames 609 */ 610int --- 535 unchanged lines hidden --- |