-
- /*
- * Handle "..": two special cases.
- * 1. If at root directory (e.g. after chroot)
- * then ignore it so can't get out.
- * 2. If this vnode is the root of a mounted
- * file system, then replace it with the
- * vnode which was mounted on so we take the
- * .. in the other file system.
- */
- if (ndp->ni_isdotdot) {
- for (;;) {
- if (dp == rootdir) {
- ndp->ni_dvp = dp;
- dp->v_count++;
- goto nextname;
- }
- if ((dp->v_flag & VROOT) == 0)
- break;
- tdp = dp;
- dp = dp->v_mount->m_vnodecovered;
- vput(tdp);
- if ((dp->v_mount->m_flag & M_EXPORTED) == 0)
- return (EACCES);
- VOP_LOCK(dp);
- dp->v_count++;
- if (rootflg)
- ndp->ni_cred->cr_uid = dp->v_mount->m_exroot;
- }
- }
-
- /*
- * We now have a segment name to search for, and a directory to search.
- */
- if (error = VOP_LOOKUP(dp, ndp)) {
- if (ndp->ni_vp != NULL)
- panic("leaf should be empty");
- /*
- * If creating and at end of pathname, then can consider
- * allowing file to be created.
- */
- if (ndp->ni_dvp->v_mount->m_flag & (M_RDONLY | M_EXRDONLY))
- error = EROFS;
- if (flag == LOOKUP || flag == DELETE || error != ENOENT)
- 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.
- */
- return (0); /* should this be ENOENT? */
- }
-
- /*
- * Check for symbolic link
- */
- dp = ndp->ni_vp;
-#ifdef notdef
- if ((dp->v_type == VLNK) &&
- (ndp->ni_nameiop & FOLLOW)) {
- struct iovec aiov;
- struct uio auio;
- int linklen;
-
- if (++ndp->ni_loopcnt > MAXSYMLINKS) {
- error = ELOOP;
- goto bad2;
- }
- MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
- aiov.iov_base = cp;
- aiov.iov_len = MAXPATHLEN;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_resid = MAXPATHLEN;
- if (error = VOP_READLINK(dp, &auio, ndp->ni_cred)) {
- free(cp, M_NAMEI);
- goto bad2;
- }
- linklen = MAXPATHLEN - auio.uio_resid;
- if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
- free(cp, M_NAMEI);
- error = ENAMETOOLONG;
- goto bad2;
- }
- bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
- ndp->ni_pnbuf = cp;
- } else
- ndp->ni_pnbuf[linklen] = '\0';
- ndp->ni_ptr = cp;
- ndp->ni_pathlen += linklen;
- vput(dp);
- dp = ndp->ni_dvp;
- goto start;
- }
-#endif
-
- /*
- * Check to see if the vnode has been mounted on;
- * if so find the root of the mounted file system.
- * Ignore NFS mount points
- */
-mntloop:
- while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
- mp->m_fsid.val[1] != MOUNT_NFS) {
- while(mp->m_flag & M_MLOCK) {
- mp->m_flag |= M_MWAIT;
- sleep((caddr_t)mp, PVFS);
- goto mntloop;
- }
- error = VFS_ROOT(mp, &tdp);
- if (error || (mp->m_flag & M_EXPORTED) == 0)
- goto bad2;
- vput(dp);
- ndp->ni_vp = dp = tdp;
- if (rootflg)
- ndp->ni_cred->cr_uid = mp->m_exroot;