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