int ntfs_lookup(void *v) { struct vop_lookup_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; } */ *ap = v; struct vnode *dvp = ap->a_dvp; struct ntnode *dip = VTONT(dvp); struct ntfsmount *ntmp = dip->i_mp; struct componentname *cnp = ap->a_cnp; kauth_cred_t cred = cnp->cn_cred; int error; dprintf(("ntfs_lookup: \"%.*s\" (%lld bytes) in %llu\n", (int)cnp->cn_namelen, cnp->cn_nameptr, (long long)cnp->cn_namelen, (unsigned long long)dip->i_number)); error = VOP_ACCESS(dvp, VEXEC, cred); if(error) return (error); if ((cnp->cn_flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); /* * We now have a segment name to search for, and a directory * to search. * * Before tediously performing a linear scan of the directory, * check the name cache to see if the directory/name pair * we are looking for is known already. */ if (cache_lookup(ap->a_dvp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_nameiop, cnp->cn_flags, NULL, ap->a_vpp)) { return *ap->a_vpp == NULLVP ? ENOENT : 0; } if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { dprintf(("ntfs_lookup: faking . directory in %llu\n", (unsigned long long)dip->i_number)); vref(dvp); *ap->a_vpp = dvp; error = 0; } else if (cnp->cn_flags & ISDOTDOT) { struct ntvattr *vap; dprintf(("ntfs_lookup: faking .. directory in %llu\n", (unsigned long long)dip->i_number)); VOP_UNLOCK(dvp); error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap); if (error) { vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); return (error); } dprintf(("ntfs_lookup: parentdir: %d\n", vap->va_a_name->n_pnumber)); error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,ap->a_vpp); ntfs_ntvattrrele(vap); vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); if (error) { return (error); } } else { error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp); if (error) { dprintf(("ntfs_ntlookupfile: returned %d\n", error)); return (error); } dprintf(("ntfs_lookup: found ino: %llu\n", (unsigned long long)VTONT(*ap->a_vpp)->i_number)); } cache_enter(dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); return error; }
int ntfs_lookup(void *v) { struct vop_lookup_args *ap = v; struct vnode *dvp = ap->a_dvp; struct ntnode *dip = VTONT(dvp); struct ntfsmount *ntmp = dip->i_mp; struct componentname *cnp = ap->a_cnp; struct ucred *cred = cnp->cn_cred; int error; int lockparent = cnp->cn_flags & LOCKPARENT; struct proc *p = cnp->cn_proc; #if NTFS_DEBUG int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); #endif dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d, lp: %d, wp: %d \n", (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen, dip->i_number, lockparent, wantparent)); error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc); if(error) return (error); if ((cnp->cn_flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); /* * We now have a segment name to search for, and a directory * to search. * * Before tediously performing a linear scan of the directory, * check the name cache to see if the directory/name pair * we are looking for is known already. */ if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0) return (error); if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { dprintf(("ntfs_lookup: faking . directory in %d\n", dip->i_number)); vref(dvp); *ap->a_vpp = dvp; error = 0; } else if (cnp->cn_flags & ISDOTDOT) { struct ntvattr *vap; dprintf(("ntfs_lookup: faking .. directory in %d\n", dip->i_number)); VOP_UNLOCK(dvp, 0, p); cnp->cn_flags |= PDIRUNLOCK; error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap); if(error) return (error); dprintf(("ntfs_lookup: parentdir: %d\n", vap->va_a_name->n_pnumber)); error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,ap->a_vpp); ntfs_ntvattrrele(vap); if (error) { if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p) == 0) cnp->cn_flags &= ~PDIRUNLOCK; return (error); } if (lockparent && (cnp->cn_flags & ISLASTCN)) { error = vn_lock(dvp, LK_EXCLUSIVE, p); if (error) { vput( *(ap->a_vpp) ); return (error); } cnp->cn_flags &= ~PDIRUNLOCK; } } else { error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp, p); if (error) { dprintf(("ntfs_ntlookupfile: returned %d\n", error)); return (error); } dprintf(("ntfs_lookup: found ino: %d\n", VTONT(*ap->a_vpp)->i_number)); if(!lockparent || (cnp->cn_flags & ISLASTCN) == 0) { VOP_UNLOCK(dvp, 0, p); cnp->cn_flags |= PDIRUNLOCK; } } if (cnp->cn_flags & MAKEENTRY) cache_enter(dvp, *ap->a_vpp, cnp); return (error); }