1*2275Swnj /* vfs_lookup.c 4.3 01/26/81 */ 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" 10*2275Swnj #include "../h/conf.h" 1130Sbill 1230Sbill /* 1330Sbill * Convert a pathname into a pointer to 1430Sbill * an inode. Note that the inode is locked. 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 2230Sbill */ 2330Sbill struct inode * 2430Sbill namei(func, flag) 2530Sbill int (*func)(); 2630Sbill { 2730Sbill register struct inode *dp; 2830Sbill register c; 2930Sbill register char *cp; 3030Sbill struct buf *bp; 31194Sbill register struct direct *ep; 3230Sbill int i; 3330Sbill dev_t d; 3430Sbill off_t eo; 3530Sbill 3630Sbill /* 3730Sbill * If name starts with '/' start from 3830Sbill * root; otherwise start from current dir. 3930Sbill */ 4030Sbill 4130Sbill dp = u.u_cdir; 4230Sbill if((c=(*func)()) == '/') 4330Sbill if ((dp = u.u_rdir) == NULL) 4430Sbill dp = rootdir; 45194Sbill (void) iget(dp->i_dev, dp->i_number); 4630Sbill while(c == '/') 4730Sbill c = (*func)(); 4830Sbill if(c == '\0' && flag != 0) 4930Sbill u.u_error = ENOENT; 5030Sbill 5130Sbill cloop: 5230Sbill /* 5330Sbill * Here dp contains pointer 5430Sbill * to last component matched. 5530Sbill */ 5630Sbill 5730Sbill if(u.u_error) 5830Sbill goto out; 5930Sbill if(c == '\0') 6030Sbill return(dp); 6130Sbill 62*2275Swnj #ifdef CHAOS 63*2275Swnj if((dp->i_mode&IFMT) == IFCHR && cdevpath & (1 << major(dp->i_un.i_rdev)) ) { 64*2275Swnj u.u_dirp--; 65*2275Swnj return(dp); 66*2275Swnj } 67*2275Swnj #endif 68*2275Swnj 6930Sbill /* 7030Sbill * If there is another component, 7130Sbill * Gather up name into 7230Sbill * users' dir buffer. 7330Sbill */ 7430Sbill 7530Sbill cp = &u.u_dbuf[0]; 7630Sbill while (c != '/' && c != '\0' && u.u_error == 0 ) { 7730Sbill if (mpxip!=NULL && c=='!') 7830Sbill break; 791777Sbill if (flag==1 && c == ('/'|0200)) { 801777Sbill u.u_error = ENOENT; 811777Sbill goto out; 821777Sbill } 83194Sbill if (cp < &u.u_dbuf[DIRSIZ]) 8430Sbill *cp++ = c; 8530Sbill c = (*func)(); 8630Sbill } 8730Sbill while(cp < &u.u_dbuf[DIRSIZ]) 8830Sbill *cp++ = '\0'; 8930Sbill while(c == '/') 9030Sbill c = (*func)(); 9130Sbill if (c == '!' && mpxip != NULL) { 9230Sbill iput(dp); 9330Sbill plock(mpxip); 9430Sbill mpxip->i_count++; 9530Sbill return(mpxip); 9630Sbill } 9730Sbill 9830Sbill seloop: 9930Sbill /* 10030Sbill * dp must be a directory and 10130Sbill * must have X permission. 10230Sbill */ 10330Sbill 10430Sbill if((dp->i_mode&IFMT) != IFDIR) 10530Sbill u.u_error = ENOTDIR; 106194Sbill (void) access(dp, IEXEC); 10730Sbill if(u.u_error) 10830Sbill goto out; 10930Sbill 11030Sbill /* 11130Sbill * set up to search a directory 11230Sbill */ 11330Sbill u.u_offset = 0; 11430Sbill u.u_segflg = 1; 11530Sbill eo = 0; 11630Sbill bp = NULL; 11730Sbill 11830Sbill eloop: 11930Sbill 12030Sbill /* 12130Sbill * If at the end of the directory, 12230Sbill * the search failed. Report what 12330Sbill * is appropriate as per flag. 12430Sbill */ 12530Sbill 12630Sbill if(u.u_offset >= dp->i_size) { 12730Sbill if(bp != NULL) 12830Sbill brelse(bp); 129265Sbill if(flag==1 && c=='\0' && dp->i_nlink) { 13030Sbill if(access(dp, IWRITE)) 13130Sbill goto out; 13230Sbill u.u_pdir = dp; 13330Sbill if(eo) 13430Sbill u.u_offset = eo-sizeof(struct direct); 13530Sbill else 13630Sbill dp->i_flag |= IUPD|ICHG; 13730Sbill return(NULL); 13830Sbill } 13930Sbill u.u_error = ENOENT; 14030Sbill goto out; 14130Sbill } 14230Sbill 14330Sbill /* 14430Sbill * If offset is on a block boundary, 14530Sbill * read the next directory block. 14630Sbill * Release previous if it exists. 14730Sbill */ 14830Sbill 14930Sbill if((u.u_offset&BMASK) == 0) { 15030Sbill if(bp != NULL) 15130Sbill brelse(bp); 15230Sbill bp = bread(dp->i_dev, 15330Sbill bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ)); 15430Sbill if (bp->b_flags & B_ERROR) { 15530Sbill brelse(bp); 15630Sbill goto out; 15730Sbill } 158194Sbill ep = (struct direct *)bp->b_un.b_addr; 159194Sbill } else 160194Sbill ep++; 16130Sbill 16230Sbill /* 16330Sbill * Note first empty directory slot 16430Sbill * in eo for possible creat. 16530Sbill * String compare the directory entry 16630Sbill * and the current component. 16730Sbill * If they do not match, go back to eloop. 16830Sbill */ 16930Sbill 17030Sbill u.u_offset += sizeof(struct direct); 171194Sbill if(ep->d_ino == 0) { 17230Sbill if(eo == 0) 17330Sbill eo = u.u_offset; 17430Sbill goto eloop; 17530Sbill } 17630Sbill for(i=0; i<DIRSIZ; i++) { 177194Sbill if(u.u_dbuf[i] != ep->d_name[i]) 17830Sbill goto eloop; 17930Sbill if(u.u_dbuf[i] == 0) 18030Sbill break; 18130Sbill } 18230Sbill 18330Sbill /* 18430Sbill * Here a component matched in a directory. 18530Sbill * If there is more pathname, go back to 18630Sbill * cloop, otherwise return. 18730Sbill */ 188194Sbill bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct)); 18930Sbill if(bp != NULL) 19030Sbill brelse(bp); 19130Sbill if(flag==2 && c=='\0') { 19230Sbill if(access(dp, IWRITE)) 19330Sbill goto out; 19430Sbill return(dp); 19530Sbill } 19630Sbill d = dp->i_dev; 19730Sbill if(u.u_dent.d_ino == ROOTINO) 19830Sbill if(dp->i_number == ROOTINO) 19930Sbill if(u.u_dent.d_name[1] == '.') 20030Sbill for(i=1; i<NMOUNT; i++) 20130Sbill if(mount[i].m_bufp != NULL) 20230Sbill if(mount[i].m_dev == d) { 20330Sbill iput(dp); 20430Sbill dp = mount[i].m_inodp; 20530Sbill dp->i_count++; 20630Sbill plock(dp); 20730Sbill goto seloop; 20830Sbill } 20930Sbill iput(dp); 21030Sbill dp = iget(d, u.u_dent.d_ino); 21130Sbill if(dp == NULL) 21230Sbill return(NULL); 21330Sbill goto cloop; 21430Sbill 21530Sbill out: 21630Sbill iput(dp); 21730Sbill return(NULL); 21830Sbill } 21930Sbill 22030Sbill /* 22130Sbill * Return the next character from the 22230Sbill * kernel string pointed at by dirp. 22330Sbill */ 22430Sbill schar() 22530Sbill { 22630Sbill 22730Sbill return(*u.u_dirp++ & 0377); 22830Sbill } 22930Sbill 23030Sbill /* 23130Sbill * Return the next character from the 23230Sbill * user string pointed at by dirp. 23330Sbill */ 23430Sbill uchar() 23530Sbill { 23630Sbill register c; 23730Sbill 23830Sbill c = fubyte(u.u_dirp++); 23930Sbill if(c == -1) 24030Sbill u.u_error = EFAULT; 24130Sbill return(c); 24230Sbill } 243