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