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