1*30Sbill /* vfs_lookup.c 3.1 10/14/12 */ 2*30Sbill 3*30Sbill #include "../h/param.h" 4*30Sbill #include "../h/systm.h" 5*30Sbill #include "../h/inode.h" 6*30Sbill #include "../h/mount.h" 7*30Sbill #include "../h/dir.h" 8*30Sbill #include "../h/user.h" 9*30Sbill #include "../h/buf.h" 10*30Sbill 11*30Sbill /* 12*30Sbill * Convert a pathname into a pointer to 13*30Sbill * an inode. Note that the inode is locked. 14*30Sbill * 15*30Sbill * func = function called to get next char of name 16*30Sbill * &uchar if name is in user space 17*30Sbill * &schar if name is in system space 18*30Sbill * flag = 0 if name is sought 19*30Sbill * 1 if name is to be created 20*30Sbill * 2 if name is to be deleted 21*30Sbill */ 22*30Sbill struct inode * 23*30Sbill namei(func, flag) 24*30Sbill int (*func)(); 25*30Sbill { 26*30Sbill register struct inode *dp; 27*30Sbill register c; 28*30Sbill register char *cp; 29*30Sbill struct buf *bp; 30*30Sbill int i; 31*30Sbill dev_t d; 32*30Sbill off_t eo; 33*30Sbill 34*30Sbill /* 35*30Sbill * If name starts with '/' start from 36*30Sbill * root; otherwise start from current dir. 37*30Sbill */ 38*30Sbill 39*30Sbill dp = u.u_cdir; 40*30Sbill if((c=(*func)()) == '/') 41*30Sbill if ((dp = u.u_rdir) == NULL) 42*30Sbill dp = rootdir; 43*30Sbill VOID iget(dp->i_dev, dp->i_number); 44*30Sbill while(c == '/') 45*30Sbill c = (*func)(); 46*30Sbill if(c == '\0' && flag != 0) 47*30Sbill u.u_error = ENOENT; 48*30Sbill 49*30Sbill cloop: 50*30Sbill /* 51*30Sbill * Here dp contains pointer 52*30Sbill * to last component matched. 53*30Sbill */ 54*30Sbill 55*30Sbill if(u.u_error) 56*30Sbill goto out; 57*30Sbill if(c == '\0') 58*30Sbill return(dp); 59*30Sbill 60*30Sbill /* 61*30Sbill * If there is another component, 62*30Sbill * Gather up name into 63*30Sbill * users' dir buffer. 64*30Sbill */ 65*30Sbill 66*30Sbill cp = &u.u_dbuf[0]; 67*30Sbill while (c != '/' && c != '\0' && u.u_error == 0 ) { 68*30Sbill if (mpxip!=NULL && c=='!') 69*30Sbill break; 70*30Sbill if(cp < &u.u_dbuf[DIRSIZ]) 71*30Sbill *cp++ = c; 72*30Sbill c = (*func)(); 73*30Sbill } 74*30Sbill while(cp < &u.u_dbuf[DIRSIZ]) 75*30Sbill *cp++ = '\0'; 76*30Sbill while(c == '/') 77*30Sbill c = (*func)(); 78*30Sbill if (c == '!' && mpxip != NULL) { 79*30Sbill iput(dp); 80*30Sbill plock(mpxip); 81*30Sbill mpxip->i_count++; 82*30Sbill return(mpxip); 83*30Sbill } 84*30Sbill 85*30Sbill seloop: 86*30Sbill /* 87*30Sbill * dp must be a directory and 88*30Sbill * must have X permission. 89*30Sbill */ 90*30Sbill 91*30Sbill if((dp->i_mode&IFMT) != IFDIR) 92*30Sbill u.u_error = ENOTDIR; 93*30Sbill VOID access(dp, IEXEC); 94*30Sbill if(u.u_error) 95*30Sbill goto out; 96*30Sbill 97*30Sbill /* 98*30Sbill * set up to search a directory 99*30Sbill */ 100*30Sbill u.u_offset = 0; 101*30Sbill u.u_segflg = 1; 102*30Sbill eo = 0; 103*30Sbill bp = NULL; 104*30Sbill 105*30Sbill eloop: 106*30Sbill 107*30Sbill /* 108*30Sbill * If at the end of the directory, 109*30Sbill * the search failed. Report what 110*30Sbill * is appropriate as per flag. 111*30Sbill */ 112*30Sbill 113*30Sbill if(u.u_offset >= dp->i_size) { 114*30Sbill if(bp != NULL) 115*30Sbill brelse(bp); 116*30Sbill if(flag==1 && c=='\0') { 117*30Sbill if(access(dp, IWRITE)) 118*30Sbill goto out; 119*30Sbill u.u_pdir = dp; 120*30Sbill if(eo) 121*30Sbill u.u_offset = eo-sizeof(struct direct); 122*30Sbill else 123*30Sbill dp->i_flag |= IUPD|ICHG; 124*30Sbill return(NULL); 125*30Sbill } 126*30Sbill u.u_error = ENOENT; 127*30Sbill goto out; 128*30Sbill } 129*30Sbill 130*30Sbill /* 131*30Sbill * If offset is on a block boundary, 132*30Sbill * read the next directory block. 133*30Sbill * Release previous if it exists. 134*30Sbill */ 135*30Sbill 136*30Sbill if((u.u_offset&BMASK) == 0) { 137*30Sbill if(bp != NULL) 138*30Sbill brelse(bp); 139*30Sbill bp = bread(dp->i_dev, 140*30Sbill bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ)); 141*30Sbill if (bp->b_flags & B_ERROR) { 142*30Sbill brelse(bp); 143*30Sbill goto out; 144*30Sbill } 145*30Sbill } 146*30Sbill 147*30Sbill /* 148*30Sbill * Note first empty directory slot 149*30Sbill * in eo for possible creat. 150*30Sbill * String compare the directory entry 151*30Sbill * and the current component. 152*30Sbill * If they do not match, go back to eloop. 153*30Sbill */ 154*30Sbill 155*30Sbill bcopy(bp->b_un.b_addr+(u.u_offset&BMASK), (caddr_t)&u.u_dent, 156*30Sbill sizeof(struct direct)); 157*30Sbill u.u_offset += sizeof(struct direct); 158*30Sbill if(u.u_dent.d_ino == 0) { 159*30Sbill if(eo == 0) 160*30Sbill eo = u.u_offset; 161*30Sbill goto eloop; 162*30Sbill } 163*30Sbill for(i=0; i<DIRSIZ; i++) { 164*30Sbill if(u.u_dbuf[i] != u.u_dent.d_name[i]) 165*30Sbill goto eloop; 166*30Sbill if(u.u_dbuf[i] == 0) 167*30Sbill break; 168*30Sbill } 169*30Sbill 170*30Sbill /* 171*30Sbill * Here a component matched in a directory. 172*30Sbill * If there is more pathname, go back to 173*30Sbill * cloop, otherwise return. 174*30Sbill */ 175*30Sbill 176*30Sbill if(bp != NULL) 177*30Sbill brelse(bp); 178*30Sbill if(flag==2 && c=='\0') { 179*30Sbill if(access(dp, IWRITE)) 180*30Sbill goto out; 181*30Sbill return(dp); 182*30Sbill } 183*30Sbill d = dp->i_dev; 184*30Sbill if(u.u_dent.d_ino == ROOTINO) 185*30Sbill if(dp->i_number == ROOTINO) 186*30Sbill if(u.u_dent.d_name[1] == '.') 187*30Sbill for(i=1; i<NMOUNT; i++) 188*30Sbill if(mount[i].m_bufp != NULL) 189*30Sbill if(mount[i].m_dev == d) { 190*30Sbill iput(dp); 191*30Sbill dp = mount[i].m_inodp; 192*30Sbill dp->i_count++; 193*30Sbill plock(dp); 194*30Sbill goto seloop; 195*30Sbill } 196*30Sbill iput(dp); 197*30Sbill dp = iget(d, u.u_dent.d_ino); 198*30Sbill if(dp == NULL) 199*30Sbill return(NULL); 200*30Sbill goto cloop; 201*30Sbill 202*30Sbill out: 203*30Sbill iput(dp); 204*30Sbill return(NULL); 205*30Sbill } 206*30Sbill 207*30Sbill /* 208*30Sbill * Return the next character from the 209*30Sbill * kernel string pointed at by dirp. 210*30Sbill */ 211*30Sbill schar() 212*30Sbill { 213*30Sbill 214*30Sbill return(*u.u_dirp++ & 0377); 215*30Sbill } 216*30Sbill 217*30Sbill /* 218*30Sbill * Return the next character from the 219*30Sbill * user string pointed at by dirp. 220*30Sbill */ 221*30Sbill uchar() 222*30Sbill { 223*30Sbill register c; 224*30Sbill 225*30Sbill c = fubyte(u.u_dirp++); 226*30Sbill if(c == -1) 227*30Sbill u.u_error = EFAULT; 228*30Sbill return(c); 229*30Sbill } 230