1*6384Swnj /* vfs_lookup.c 4.14 82/03/31 */ 230Sbill 330Sbill #include "../h/param.h" 430Sbill #include "../h/systm.h" 530Sbill #include "../h/inode.h" 630Sbill #include "../h/mount.h" 730Sbill #include "../h/dir.h" 830Sbill #include "../h/user.h" 930Sbill #include "../h/buf.h" 102275Swnj #include "../h/conf.h" 1130Sbill 1230Sbill /* 1330Sbill * Convert a pathname into a pointer to 145972Swnj * a locked inode. 1530Sbill * 1630Sbill * func = function called to get next char of name 1730Sbill * &uchar if name is in user space 1830Sbill * &schar if name is in system space 1930Sbill * flag = 0 if name is sought 2030Sbill * 1 if name is to be created 2130Sbill * 2 if name is to be deleted 225972Swnj * follow = 1 if links are to be followed at the end of the name 2330Sbill */ 2430Sbill struct inode * 255972Swnj namei(func, flag, follow) 265972Swnj int (*func)(), flag, follow; 2730Sbill { 2830Sbill register struct inode *dp; 2930Sbill register char *cp; 305972Swnj register struct buf *bp, *nbp; 31194Sbill register struct direct *ep; 325990Swnj struct inode *pdp; 335972Swnj int i, nlink; 3430Sbill dev_t d; 3530Sbill off_t eo; 3630Sbill 3730Sbill /* 385972Swnj * allocate name buffer; copy name 395972Swnj */ 405972Swnj nbp = geteblk(); 415972Swnj nlink = 0; 425972Swnj for (i=0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) { 436066Sroot if ((*cp&0377) == ('/'|0200)) { 446066Sroot u.u_error = EPERM; 456066Sroot break; 466066Sroot } 476066Sroot #ifdef notdef 485972Swnj if (*cp++&0200 && flag==1 || cp >= nbp->b_un.b_addr+BSIZE) { 496066Sroot #else 506066Sroot cp++; 516066Sroot if (cp >= nbp->b_un.b_addr+BSIZE) { 526066Sroot #endif 535972Swnj u.u_error = ENOENT; 545972Swnj break; 555972Swnj } 565972Swnj } 575972Swnj if (u.u_error) { 585972Swnj dp = NULL; 595972Swnj goto out1; 605972Swnj } 615972Swnj cp = nbp->b_un.b_addr; 625972Swnj /* 6330Sbill * If name starts with '/' start from 6430Sbill * root; otherwise start from current dir. 6530Sbill */ 6630Sbill dp = u.u_cdir; 675972Swnj if (*cp == '/') { 685972Swnj while (*cp == '/') 695972Swnj cp++; 7030Sbill if ((dp = u.u_rdir) == NULL) 7130Sbill dp = rootdir; 7230Sbill } 735972Swnj ilock(dp); 745972Swnj dp->i_count++; 7530Sbill 7630Sbill /* 7730Sbill * dp must be a directory and 7830Sbill * must have X permission. 795972Swnj * cp is a path name relative to that directory. 8030Sbill */ 8130Sbill 825972Swnj dirloop: 834823Swnj if ((dp->i_mode&IFMT) != IFDIR) 8430Sbill u.u_error = ENOTDIR; 85194Sbill (void) access(dp, IEXEC); 86*6384Swnj dirloop2: 875972Swnj for (i=0; *cp!='\0' && *cp!='/'; i++) { 886066Sroot #ifdef notdef 895972Swnj if (i >= DIRSIZ) { 905972Swnj u.u_error = ENOENT; 915972Swnj break; 925972Swnj } 935972Swnj u.u_dbuf[i] = *cp++; 946066Sroot #else 956066Sroot if (i < DIRSIZ) 966066Sroot u.u_dbuf[i] = *cp; 976066Sroot cp++; 986066Sroot #endif 995972Swnj } 1004823Swnj if (u.u_error) 10130Sbill goto out; 1025990Swnj u.u_pdir = dp; 1035972Swnj while (i < DIRSIZ) 1045972Swnj u.u_dbuf[i++] = '\0'; 1055972Swnj if (u.u_dbuf[0] == '\0') { /* null name, e.g. "/" or "" */ 1065972Swnj if (flag) { 1075972Swnj u.u_error = ENOENT; 1085972Swnj goto out; 1095972Swnj } 1105972Swnj goto out1; 1115972Swnj } 11230Sbill u.u_segflg = 1; 1135972Swnj eo = -1; 11430Sbill bp = NULL; 11530Sbill 1165972Swnj for (u.u_offset=0; u.u_offset < dp->i_size; 1175972Swnj u.u_offset += sizeof(struct direct), ep++) { 1185972Swnj /* 1195972Swnj * If offset is on a block boundary, 1205972Swnj * read the next directory block. 1215972Swnj * Release previous if it exists. 1225972Swnj */ 1235972Swnj if ((u.u_offset&BMASK) == 0) { 1245972Swnj if (bp != NULL) 1255972Swnj brelse(bp); 1265972Swnj bp = bread(dp->i_dev, 1275972Swnj bmap(dp,(daddr_t)(u.u_offset>>BSHIFT), B_READ)); 1285972Swnj if (bp->b_flags & B_ERROR) { 1295972Swnj brelse(bp); 1305972Swnj goto out; 1315972Swnj } 1325972Swnj ep = (struct direct *)bp->b_un.b_addr; 1335972Swnj } 1345972Swnj /* 1355972Swnj * Note first empty directory slot 1365972Swnj * in eo for possible creat. 1375972Swnj * String compare the directory entry 1385972Swnj * and the current component. 1395972Swnj */ 1405972Swnj if (ep->d_ino == 0) { 1415972Swnj if (eo < 0) 1425972Swnj eo = u.u_offset; 1435972Swnj continue; 1445972Swnj } 1455972Swnj if (strncmp(u.u_dbuf, ep->d_name, DIRSIZ) != 0) 1465972Swnj continue; 1475972Swnj /* 1485972Swnj * Here a component matched in a directory. 1495972Swnj * If there is more pathname, go back to 1505972Swnj * dirloop, otherwise return. 1515972Swnj */ 1525972Swnj bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct)); 1535972Swnj brelse(bp); 1545972Swnj if (flag==2 && *cp=='\0') { 1554823Swnj if (access(dp, IWRITE)) 15630Sbill goto out; 1575972Swnj /* should fix unlink */ 1585972Swnj u.u_offset += sizeof(struct direct); 1595972Swnj goto out1; 16030Sbill } 1615972Swnj /* 1625972Swnj * Special handling for ".." 1635972Swnj */ 1645972Swnj if (u.u_dent.d_name[0]=='.' && u.u_dent.d_name[1]=='.' && 1655972Swnj u.u_dent.d_name[2]=='\0') { 1665972Swnj if (dp == u.u_rdir) 1675972Swnj u.u_dent.d_ino = dp->i_number; 1685972Swnj else if (u.u_dent.d_ino==ROOTINO && 1695972Swnj dp->i_number == ROOTINO) { 1705972Swnj for(i=1; i<NMOUNT; i++) 1715972Swnj if (mount[i].m_bufp != NULL && 1725972Swnj mount[i].m_dev == dp->i_dev) { 1735972Swnj iput(dp); 1745972Swnj dp = mount[i].m_inodp; 1755972Swnj ilock(dp); 1765972Swnj dp->i_count++; 1775972Swnj cp -= 2; /* back over .. */ 178*6384Swnj goto dirloop2; 1795972Swnj } 1805972Swnj } 1815972Swnj } 1825972Swnj d = dp->i_dev; 1835990Swnj irele(dp); 1845990Swnj pdp = dp; 1855972Swnj dp = iget(d, u.u_dent.d_ino); 1865990Swnj if (dp == NULL) { 1875990Swnj iput(pdp); 1885972Swnj goto out1; 1895990Swnj } 1905972Swnj /* 1915972Swnj * Check for symbolic link 1925972Swnj */ 1935972Swnj if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp=='/')) { 1945972Swnj char *ocp; 19530Sbill 1965972Swnj ocp = cp; 1975972Swnj while (*cp++) 1985972Swnj ; 1995972Swnj if (dp->i_size + (cp-ocp) >= BSIZE-1 || ++nlink>8) { 2005972Swnj u.u_error = ELOOP; 2015990Swnj iput(pdp); 2025972Swnj goto out; 2035972Swnj } 2046164Ssam bcopy(ocp, nbp->b_un.b_addr+dp->i_size, 2056164Ssam (unsigned)(cp-ocp)); 2065972Swnj bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ)); 2075972Swnj if (bp->b_flags & B_ERROR) { 2085972Swnj brelse(bp); 2095990Swnj iput(pdp); 2105972Swnj goto out; 2115972Swnj } 2126164Ssam bcopy(bp->b_un.b_addr, nbp->b_un.b_addr, 2136164Ssam (unsigned)dp->i_size); 21430Sbill brelse(bp); 2155972Swnj cp = nbp->b_un.b_addr; 2165972Swnj iput(dp); 2175972Swnj if (*cp == '/') { 2185990Swnj iput(pdp); 2195972Swnj while (*cp == '/') 2205972Swnj cp++; 2215972Swnj if ((dp = u.u_rdir) == NULL) 2225972Swnj dp = rootdir; 2235972Swnj ilock(dp); 2245972Swnj dp->i_count++; 2255972Swnj } else { 2265990Swnj dp = pdp; 2275990Swnj ilock(dp); 2285972Swnj } 2295972Swnj goto dirloop; 23030Sbill } 2315990Swnj iput(pdp); 2325972Swnj if (*cp == '/') { 2335972Swnj while (*cp == '/') 2345972Swnj cp++; 2355972Swnj goto dirloop; 2365972Swnj } 2375972Swnj goto out1; 23830Sbill } 23930Sbill /* 2405972Swnj * Search failed. 24130Sbill */ 2424823Swnj if (bp != NULL) 24330Sbill brelse(bp); 2445972Swnj if (flag==1 && *cp=='\0' && dp->i_nlink) { 2454823Swnj if (access(dp, IWRITE)) 24630Sbill goto out; 2475972Swnj if (eo>=0) 2485972Swnj u.u_offset = eo; 2495972Swnj dp->i_flag |= IUPD|ICHG; 2505972Swnj dp = NULL; 2515972Swnj goto out1; 25230Sbill } 2535972Swnj u.u_error = ENOENT; 25430Sbill out: 25530Sbill iput(dp); 2565972Swnj dp = NULL; 2575972Swnj out1: 2585972Swnj brelse(nbp); 2595972Swnj return (dp); 26030Sbill } 26130Sbill 26230Sbill /* 26330Sbill * Return the next character from the 26430Sbill * kernel string pointed at by dirp. 26530Sbill */ 26630Sbill schar() 26730Sbill { 26830Sbill 2695972Swnj return (*u.u_dirp++ & 0377); 27030Sbill } 27130Sbill 27230Sbill /* 27330Sbill * Return the next character from the 27430Sbill * user string pointed at by dirp. 27530Sbill */ 27630Sbill uchar() 27730Sbill { 27830Sbill register c; 27930Sbill 28030Sbill c = fubyte(u.u_dirp++); 2815972Swnj if (c == -1) { 28230Sbill u.u_error = EFAULT; 2835972Swnj c = 0; 2845972Swnj } 2855972Swnj return (c); 28630Sbill } 2875972Swnj 2885972Swnj #ifndef vax 2895972Swnj strncmp(s1, s2, len) 2905972Swnj register char *s1, *s2; 2915972Swnj register len; 2925972Swnj { 2935972Swnj 2945972Swnj do { 2955972Swnj if (*s1 != *s2++) 2965972Swnj return (1); 2975972Swnj if (*s1++ == '\0') 2985972Swnj return (0); 2995972Swnj } while (--len); 3005972Swnj return (0); 3015972Swnj } 3025972Swnj #endif 303