if (!dp->v_mount) {  FREE(cnp->cn_pnbuf, M_NAMEI); return (ENOENT); }
namei(ndp)	register struct nameidata *ndp;{	register struct filedesc *fdp;	/* pointer to file descriptor state */	register char *cp;		/* pointer into pathname argument */	register struct vnode *dp;	/* the directory we are searching */	struct iovec aiov;		/* uio for reading symbolic links */	struct uio auio;	int error, linklen;	struct componentname *cnp = &ndp->ni_cnd;	struct proc *p = cnp->cn_proc;	ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;#ifdef DIAGNOSTIC	if (!cnp->cn_cred || !cnp->cn_proc)		panic ("namei: bad cred/proc");	if (cnp->cn_nameiop & (~OPMASK))		panic ("namei: nameiop contaminated with flags");	if (cnp->cn_flags & OPMASK)		panic ("namei: flags contaminated with nameiops");#endif	fdp = cnp->cn_proc->p_fd;	/*	 * Get a buffer for the name to be translated, and copy the	 * name into the buffer.	 */	if ((cnp->cn_flags & HASBUF) == 0)		MALLOC(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);	if (ndp->ni_segflg == UIO_SYSSPACE)		error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,			    MAXPATHLEN, &ndp->ni_pathlen);	else		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,			    MAXPATHLEN, &ndp->ni_pathlen);	/*	 * Fail on null pathnames	 */	if (error == 0 && ndp->ni_pathlen == 1)		error = ENOENT;	if (error) {		FREE(cnp->cn_pnbuf, M_NAMEI);		ndp->ni_vp = NULL;		return (error);	}#ifdef KTRACE	if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))		ktrnamei(cnp->cn_proc, cnp->cn_pnbuf);#endif	/*	 *  Strip trailing slashes, as requested	 */	if (cnp->cn_flags & STRIPSLASHES) {		char *end = cnp->cn_pnbuf + ndp->ni_pathlen - 2;		cp = end;		while (cp >= cnp->cn_pnbuf && (*cp == '/'))			cp--;		/* Still some remaining characters in the buffer */		if (cp >= cnp->cn_pnbuf) {			ndp->ni_pathlen -= (end - cp);			*(cp + 1) = '\0';		}	}	ndp->ni_loopcnt = 0;	/*	 * Get starting point for the translation.	 */	if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL)		ndp->ni_rootdir = rootvnode;	/*	 * Check if starting from root directory or current directory.	 */	if (cnp->cn_pnbuf[0] == '/') {		dp = ndp->ni_rootdir;		VREF(dp);	} else {		dp = fdp->fd_cdir;		VREF(dp);	}	for (;;) {		cnp->cn_nameptr = cnp->cn_pnbuf;		ndp->ni_startdir = dp;		if ((error = lookup(ndp)) != 0) {			FREE(cnp->cn_pnbuf, M_NAMEI);			return (error);		}		/*		 * Check for symbolic link		 */		if ((cnp->cn_flags & ISSYMLINK) == 0) {			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)				FREE(cnp->cn_pnbuf, M_NAMEI);			else				cnp->cn_flags |= HASBUF;			return (0);		}		if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))			VOP_UNLOCK(ndp->ni_dvp, 0, p);		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {			error = ELOOP;			break;		}		if (ndp->ni_pathlen > 1)			MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);		else			cp = cnp->cn_pnbuf;		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_procp = (struct proc *)0;		auio.uio_resid = MAXPATHLEN;		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);		if (error) {badlink:			if (ndp->ni_pathlen > 1)				FREE(cp, M_NAMEI);			break;		}		linklen = MAXPATHLEN - auio.uio_resid;		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {			error = ENAMETOOLONG;			goto badlink;		}		if (ndp->ni_pathlen > 1) {			bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);			FREE(cnp->cn_pnbuf, M_NAMEI);			cnp->cn_pnbuf = cp;		} else			cnp->cn_pnbuf[linklen] = '\0';		ndp->ni_pathlen += linklen;		vput(ndp->ni_vp);		dp = ndp->ni_dvp;		/*		 * Check if root directory should replace current directory.		 */		if (cnp->cn_pnbuf[0] == '/') {			vrele(dp);			dp = ndp->ni_rootdir;			VREF(dp);		}	}	FREE(cnp->cn_pnbuf, M_NAMEI);	vrele(ndp->ni_dvp);	vput(ndp->ni_vp);	ndp->ni_vp = NULL;	return (error);}