- if (isdotdot) {
- iunlock(pdp); /* race to get the inode */
- dp = iget(dp->i_dev, fs, u.u_dent.d_ino);
- if (dp == NULL)
- goto bad2;
- } else if (dp->i_number == u.u_dent.d_ino) {
- dp->i_count++; /* we want ourself, ie "." */
- } else {
- dp = iget(dp->i_dev, fs, u.u_dent.d_ino);
- iunlock(pdp);
- if (dp == NULL)
- goto bad2;
- }
-
- /*
- * insert name into cache (if we want it, and it isn't "." or "..")
- *
- * all other cases where making a cache entry would be wrong
- * have already departed from the code sequence somewhere above.
- */
- if (bcmp(u.u_dent.d_name, ".", 2) != 0 && !isdotdot && docache) {
- if (ncp != NULL)
- panic("nami: 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;
-
- /* remove from old hash chain */
- remque(ncp);
-
- /* drop hold on inode (if we had one) */
- if (ncp->nc_ip)
- irele(ncp->nc_ip);
-
- /* grab the inode we just found */
- ncp->nc_ip = dp;
- dp->i_count++;
-
- /* 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_nlen = u.u_dent.d_namlen;
- bcopy(u.u_dent.d_name, ncp->nc_name, 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 && (follow || *cp == '/')) {
- u_int pathlen = strlen(cp) + 1;
-
- if (dp->i_size + pathlen >= MAXPATHLEN - 1 ||
- ++nlink > MAXSYMLINKS) {
- u.u_error = ELOOP;
- goto bad2;
- }
- ovbcopy(cp, nbp->b_un.b_addr + dp->i_size, pathlen);
- u.u_error =
- rdwri(UIO_READ, dp, nbp->b_un.b_addr, (int)dp->i_size,
- 0, 1, (int *)0);
- if (u.u_error)
- goto bad2;
- cp = nbp->b_un.b_addr;
- 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);