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