📄 vfs_lookup.c
字号:
goto bad; } if (wantparent) { ndp->ni_dvp = dp; VREF(dp); } ndp->ni_vp = dp; if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF))) VOP_UNLOCK(dp); if (cnp->cn_flags & SAVESTART) panic("lookup: SAVESTART"); return (0); } /* * Handle "..": two special cases. * 1. If at root directory (e.g. after chroot) * or at absolute root directory * then ignore it so can't get out. * 2. If this vnode is the root of a mounted * filesystem, then replace it with the * vnode which was mounted on so we take the * .. in the other file system. */ if (cnp->cn_flags & ISDOTDOT) { for (;;) { if (dp == ndp->ni_rootdir || dp == rootvnode) { ndp->ni_dvp = dp; ndp->ni_vp = dp; VREF(dp); goto nextname; } if ((dp->v_flag & VROOT) == 0 || (cnp->cn_flags & NOCROSSMOUNT)) break; tdp = dp; dp = dp->v_mount->mnt_vnodecovered; vput(tdp); VREF(dp); VOP_LOCK(dp); } } /* * We now have a segment name to search for, and a directory to search. */unionlookup: ndp->ni_dvp = dp; if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {#ifdef DIAGNOSTIC if (ndp->ni_vp != NULL) panic("leaf should be empty");#endif#ifdef NAMEI_DIAGNOSTIC printf("not found\n");#endif if ((error == ENOENT) && (dp->v_flag & VROOT) && (dp->v_mount->mnt_flag & MNT_UNION)) { tdp = dp; dp = dp->v_mount->mnt_vnodecovered; vput(tdp); VREF(dp); VOP_LOCK(dp); goto unionlookup; } if (error != EJUSTRETURN) goto bad; /* * If creating and at end of pathname, then can consider * allowing file to be created. */ if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { error = EROFS; goto bad; } /* * We return with ni_vp NULL to indicate that the entry * doesn't currently exist, leaving a pointer to the * (possibly locked) directory inode in ndp->ni_dvp. */ if (cnp->cn_flags & SAVESTART) { ndp->ni_startdir = ndp->ni_dvp; VREF(ndp->ni_startdir); } return (0); }#ifdef NAMEI_DIAGNOSTIC printf("found\n");#endif /* * Take into account any additional components consumed by * the underlying filesystem. */ if (cnp->cn_consume > 0) { cnp->cn_nameptr += cnp->cn_consume; ndp->ni_next += cnp->cn_consume; ndp->ni_pathlen -= cnp->cn_consume; cnp->cn_consume = 0; } dp = ndp->ni_vp; /* * Check to see if the vnode has been mounted on; * if so find the root of the mounted file system. */ while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && (cnp->cn_flags & NOCROSSMOUNT) == 0) { if (mp->mnt_flag & MNT_MLOCK) { mp->mnt_flag |= MNT_MWAIT; sleep((caddr_t)mp, PVFS); continue; } if ((error = VFS_ROOT(dp->v_mountedhere, &tdp)) != 0) goto bad2; vput(dp); ndp->ni_vp = dp = tdp; } /* * Check for symbolic link */ if ((dp->v_type == VLNK) && ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { cnp->cn_flags |= ISSYMLINK; return (0); }nextname: /* * Not a symbolic link. If more pathname, * continue at next component, else return. */ if (*ndp->ni_next == '/') { cnp->cn_nameptr = ndp->ni_next; while (*cnp->cn_nameptr == '/') { cnp->cn_nameptr++; ndp->ni_pathlen--; } vrele(ndp->ni_dvp); goto dirloop; } /* * Check for read-only file systems. */ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { /* * Disallow directory write attempts on read-only * file systems. */ if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || (wantparent && (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { error = EROFS; goto bad2; } } if (cnp->cn_flags & SAVESTART) { ndp->ni_startdir = ndp->ni_dvp; VREF(ndp->ni_startdir); } if (!wantparent) vrele(ndp->ni_dvp); if ((cnp->cn_flags & LOCKLEAF) == 0) VOP_UNLOCK(dp); return (0);bad2: if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0') VOP_UNLOCK(ndp->ni_dvp); vrele(ndp->ni_dvp);bad: vput(dp); ndp->ni_vp = NULL; return (error);}/* * Reacquire a path name component. */intrelookup(dvp, vpp, cnp) struct vnode *dvp, **vpp; struct componentname *cnp;{ register struct vnode *dp = 0; /* the directory we are searching */ int docache; /* == 0 do not cache last component */ int wantparent; /* 1 => wantparent or lockparent flag */ int rdonly; /* lookup read-only flag bit */ int error = 0;#ifdef NAMEI_DIAGNOSTIC int newhash; /* DEBUG: check name hash */ char *cp; /* DEBUG: check name ptr/len */#endif /* * Setup: break out flag bits into variables. */ wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; if (cnp->cn_nameiop == DELETE || (wantparent && cnp->cn_nameiop != CREATE)) docache = 0; rdonly = cnp->cn_flags & RDONLY; cnp->cn_flags &= ~ISSYMLINK; dp = dvp; VOP_LOCK(dp);/* dirloop: */ /* * Search a new directory. * * The cn_hash value is for use by vfs_cache. * The last component of the filename is left accessible via * cnp->cn_nameptr for callers that need the name. Callers needing * the name set the SAVENAME flag. When done, they assume * responsibility for freeing the pathname buffer. */#ifdef NAMEI_DIAGNOSTIC for (newhash = 0, cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) newhash += (unsigned char)*cp; if (newhash != cnp->cn_hash) panic("relookup: bad hash"); if (cnp->cn_namelen != cp - cnp->cn_nameptr) panic ("relookup: bad len"); if (*cp != 0) panic("relookup: not last component"); printf("{%s}: ", cnp->cn_nameptr);#endif /* * Check for degenerate name (e.g. / or "") * which is a way of talking about a directory, * e.g. like "/." or ".". */ if (cnp->cn_nameptr[0] == '\0') { if (dp->v_type != VDIR) { error = ENOTDIR; goto bad; } if (cnp->cn_nameiop != LOOKUP || wantparent) { error = EISDIR; goto bad; } if (!(cnp->cn_flags & LOCKLEAF)) VOP_UNLOCK(dp); *vpp = dp; if (cnp->cn_flags & SAVESTART) panic("lookup: SAVESTART"); return (0); } if (cnp->cn_flags & ISDOTDOT) panic ("relookup: lookup on dot-dot"); /* * We now have a segment name to search for, and a directory to search. */ if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) {#ifdef DIAGNOSTIC if (*vpp != NULL) panic("leaf should be empty");#endif if (error != EJUSTRETURN) goto bad; /* * If creating and at end of pathname, then can consider * allowing file to be created. */ if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) { error = EROFS; goto bad; } /* ASSERT(dvp == ndp->ni_startdir) */ if (cnp->cn_flags & SAVESTART) VREF(dvp); /* * We return with ni_vp NULL to indicate that the entry * doesn't currently exist, leaving a pointer to the * (possibly locked) directory inode in ndp->ni_dvp. */ return (0); } dp = *vpp;#ifdef DIAGNOSTIC /* * Check for symbolic link */ if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) panic ("relookup: symlink found.\n");#endif /* * Check for read-only file systems. */ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { /* * Disallow directory write attempts on read-only * file systems. */ if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || (wantparent && (dvp->v_mount->mnt_flag & MNT_RDONLY))) { error = EROFS; goto bad2; } } /* ASSERT(dvp == ndp->ni_startdir) */ if (cnp->cn_flags & SAVESTART) VREF(dvp); if (!wantparent) vrele(dvp); if ((cnp->cn_flags & LOCKLEAF) == 0) VOP_UNLOCK(dp); return (0);bad2: if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) VOP_UNLOCK(dvp); vrele(dvp);bad: vput(dp); *vpp = NULL; return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -