- if (makeentry) {
- if (ncp != NULL)
- panic("namei: duplicating cache");
- /*
- * Free the cache slot at head of lru chain.
- */
- if (ncp = nchhead) {
- /* remove from lru chain */
- *ncp->nc_prev = ncp->nc_nxt;
- if (ncp->nc_nxt)
- ncp->nc_nxt->nc_prev = ncp->nc_prev;
- else
- nchtail = ncp->nc_prev;
- remque(ncp); /* remove from old hash chain */
- /* grab the inode we just found */
- ncp->nc_ip = dp;
- /* fill in cache info */
- ncp->nc_ino = pdp->i_number; /* parents inum */
- ncp->nc_dev = pdp->i_dev; /* & device */
- ncp->nc_idev = dp->i_dev; /* our device */
- ncp->nc_id = dp->i_id; /* identifier */
- ncp->nc_nlen = ndp->ni_dent.d_namlen;
- bcopy(ndp->ni_dent.d_name, ncp->nc_name,
- (unsigned)ncp->nc_nlen);
- /* link at end of lru chain */
- ncp->nc_nxt = NULL;
- ncp->nc_prev = nchtail;
- *nchtail = ncp;
- nchtail = &ncp->nc_nxt;
- /* and insert on hash chain */
- insque(ncp, nhp);
- }
- }
-
-haveino:
- fs = dp->i_fs;
-
- /*
- * Check for symbolic link
- */
- if ((dp->i_mode & IFMT) == IFLNK &&
- ((ndp->ni_nameiop & FOLLOW) || *cp == '/')) {
- u_int pathlen = strlen(cp) + 1;
-
- if (dp->i_size + pathlen >= MAXPATHLEN - 1) {
- u.u_error = ENAMETOOLONG;
- goto bad2;
- }
- if (++nlink > MAXSYMLINKS) {
- u.u_error = ELOOP;
- goto bad2;
- }
- ovbcopy(cp, nbp + dp->i_size, pathlen);
- u.u_error =
- rdwri(UIO_READ, dp, nbp, (int)dp->i_size,
- (off_t)0, 1, (int *)0);
- if (u.u_error)
- goto bad2;
- cp = nbp;
- iput(dp);
- if (*cp == '/') {
- irele(pdp);
- while (*cp == '/')
- cp++;
- if ((dp = u.u_rdir) == NULL)
- dp = rootdir;
- ILOCK(dp);
- dp->i_count++;
- } else {
- dp = pdp;
- ILOCK(dp);
- }
- fs = dp->i_fs;
- goto dirloop;
- }
-
- /*
- * Not a symbolic link. If more pathname,
- * continue at next component, else return.
- */
- if (*cp == '/') {
- while (*cp == '/')
- cp++;
- irele(pdp);
- goto dirloop;
- }
- FREE(nbp, M_NAMEI);
- if (lockparent)
- ndp->ni_pdir = pdp;
- else
- irele(pdp);
- return (dp);
-bad2:
- irele(pdp);
-bad:
- if (bp)
- brelse(bp);
- if (dp)
- iput(dp);
- FREE(nbp, M_NAMEI);
- return (NULL);