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