1 /* ufs_lookup.c 4.11 82/03/06 */ 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 * a locked inode. 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 * follow = 1 if links are to be followed at the end of the name 23 */ 24 struct inode * 25 namei(func, flag, follow) 26 int (*func)(), flag, follow; 27 { 28 register struct inode *dp; 29 register char *cp; 30 register struct buf *bp, *nbp; 31 register struct direct *ep; 32 struct inode *pdp; 33 int i, nlink; 34 dev_t d; 35 ino_t ino; 36 off_t eo; 37 38 /* 39 * allocate name buffer; copy name 40 */ 41 nbp = geteblk(); 42 nlink = 0; 43 for (i=0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) { 44 if ((*cp&0377) == ('/'|0200)) { 45 u.u_error = EPERM; 46 break; 47 } 48 #ifdef notdef 49 if (*cp++&0200 && flag==1 || cp >= nbp->b_un.b_addr+BSIZE) { 50 #else 51 cp++; 52 if (cp >= nbp->b_un.b_addr+BSIZE) { 53 #endif 54 u.u_error = ENOENT; 55 break; 56 } 57 } 58 if (u.u_error) { 59 dp = NULL; 60 goto out1; 61 } 62 cp = nbp->b_un.b_addr; 63 /* 64 * If name starts with '/' start from 65 * root; otherwise start from current dir. 66 */ 67 dp = u.u_cdir; 68 if (*cp == '/') { 69 while (*cp == '/') 70 cp++; 71 if ((dp = u.u_rdir) == NULL) 72 dp = rootdir; 73 } 74 ilock(dp); 75 dp->i_count++; 76 77 /* 78 * dp must be a directory and 79 * must have X permission. 80 * cp is a path name relative to that directory. 81 */ 82 83 dirloop: 84 if ((dp->i_mode&IFMT) != IFDIR) 85 u.u_error = ENOTDIR; 86 (void) access(dp, IEXEC); 87 for (i=0; *cp!='\0' && *cp!='/'; i++) { 88 #ifdef notdef 89 if (i >= DIRSIZ) { 90 u.u_error = ENOENT; 91 break; 92 } 93 u.u_dbuf[i] = *cp++; 94 #else 95 if (i < DIRSIZ) 96 u.u_dbuf[i] = *cp; 97 cp++; 98 #endif 99 } 100 if (u.u_error) 101 goto out; 102 u.u_pdir = dp; 103 while (i < DIRSIZ) 104 u.u_dbuf[i++] = '\0'; 105 if (u.u_dbuf[0] == '\0') { /* null name, e.g. "/" or "" */ 106 if (flag) { 107 u.u_error = ENOENT; 108 goto out; 109 } 110 goto out1; 111 } 112 u.u_segflg = 1; 113 eo = -1; 114 bp = NULL; 115 116 for (u.u_offset=0; u.u_offset < dp->i_size; 117 u.u_offset += sizeof(struct direct), ep++) { 118 /* 119 * If offset is on a block boundary, 120 * read the next directory block. 121 * Release previous if it exists. 122 */ 123 if ((u.u_offset&BMASK) == 0) { 124 if (bp != NULL) 125 brelse(bp); 126 bp = bread(dp->i_dev, 127 bmap(dp,(daddr_t)(u.u_offset>>BSHIFT), B_READ)); 128 if (bp->b_flags & B_ERROR) { 129 brelse(bp); 130 goto out; 131 } 132 ep = (struct direct *)bp->b_un.b_addr; 133 } 134 /* 135 * Note first empty directory slot 136 * in eo for possible creat. 137 * String compare the directory entry 138 * and the current component. 139 */ 140 if (ep->d_ino == 0) { 141 if (eo < 0) 142 eo = u.u_offset; 143 continue; 144 } 145 if (strncmp(u.u_dbuf, ep->d_name, DIRSIZ) != 0) 146 continue; 147 /* 148 * Here a component matched in a directory. 149 * If there is more pathname, go back to 150 * dirloop, otherwise return. 151 */ 152 bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct)); 153 brelse(bp); 154 if (flag==2 && *cp=='\0') { 155 if (access(dp, IWRITE)) 156 goto out; 157 /* should fix unlink */ 158 u.u_offset += sizeof(struct direct); 159 goto out1; 160 } 161 /* 162 * Special handling for ".." 163 */ 164 if (u.u_dent.d_name[0]=='.' && u.u_dent.d_name[1]=='.' && 165 u.u_dent.d_name[2]=='\0') { 166 if (dp == u.u_rdir) 167 u.u_dent.d_ino = dp->i_number; 168 else if (u.u_dent.d_ino==ROOTINO && 169 dp->i_number == ROOTINO) { 170 for(i=1; i<NMOUNT; i++) 171 if (mount[i].m_bufp != NULL && 172 mount[i].m_dev == dp->i_dev) { 173 iput(dp); 174 dp = mount[i].m_inodp; 175 ilock(dp); 176 dp->i_count++; 177 cp -= 2; /* back over .. */ 178 goto dirloop; 179 } 180 } 181 } 182 d = dp->i_dev; 183 ino = dp->i_number; 184 irele(dp); 185 pdp = dp; 186 dp = iget(d, u.u_dent.d_ino); 187 if (dp == NULL) { 188 iput(pdp); 189 goto out1; 190 } 191 /* 192 * Check for symbolic link 193 */ 194 if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp=='/')) { 195 char *ocp; 196 197 ocp = cp; 198 while (*cp++) 199 ; 200 if (dp->i_size + (cp-ocp) >= BSIZE-1 || ++nlink>8) { 201 u.u_error = ELOOP; 202 iput(pdp); 203 goto out; 204 } 205 bcopy(ocp, nbp->b_un.b_addr+dp->i_size, cp-ocp); 206 bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ)); 207 if (bp->b_flags & B_ERROR) { 208 brelse(bp); 209 iput(pdp); 210 goto out; 211 } 212 bcopy(bp->b_un.b_addr, nbp->b_un.b_addr, dp->i_size); 213 brelse(bp); 214 cp = nbp->b_un.b_addr; 215 iput(dp); 216 if (*cp == '/') { 217 iput(pdp); 218 while (*cp == '/') 219 cp++; 220 if ((dp = u.u_rdir) == NULL) 221 dp = rootdir; 222 ilock(dp); 223 dp->i_count++; 224 } else { 225 dp = pdp; 226 ilock(dp); 227 } 228 goto dirloop; 229 } 230 iput(pdp); 231 if (*cp == '/') { 232 while (*cp == '/') 233 cp++; 234 goto dirloop; 235 } 236 goto out1; 237 } 238 /* 239 * Search failed. 240 */ 241 if (bp != NULL) 242 brelse(bp); 243 if (flag==1 && *cp=='\0' && dp->i_nlink) { 244 if (access(dp, IWRITE)) 245 goto out; 246 if (eo>=0) 247 u.u_offset = eo; 248 dp->i_flag |= IUPD|ICHG; 249 dp = NULL; 250 goto out1; 251 } 252 u.u_error = ENOENT; 253 out: 254 iput(dp); 255 dp = NULL; 256 out1: 257 brelse(nbp); 258 return (dp); 259 } 260 261 /* 262 * Return the next character from the 263 * kernel string pointed at by dirp. 264 */ 265 schar() 266 { 267 268 return (*u.u_dirp++ & 0377); 269 } 270 271 /* 272 * Return the next character from the 273 * user string pointed at by dirp. 274 */ 275 uchar() 276 { 277 register c; 278 279 c = fubyte(u.u_dirp++); 280 if (c == -1) { 281 u.u_error = EFAULT; 282 c = 0; 283 } 284 return (c); 285 } 286 287 #ifndef vax 288 strncmp(s1, s2, len) 289 register char *s1, *s2; 290 register len; 291 { 292 293 do { 294 if (*s1 != *s2++) 295 return (1); 296 if (*s1++ == '\0') 297 return (0); 298 } while (--len); 299 return (0); 300 } 301 #endif 302