7500: # 7501: #include "../param.h" 7502: #include "../inode.h" 7503: #include "../user.h" 7504: #include "../systm.h" 7505: #include "../buf.h" 7506: 7507: /* 7508: * Convert a pathname into a pointer to 7509: * an inode. Note that the inode is locked. 7510: * 7511: * func = function called to get next char of name 7512: * &uchar if name is in user space 7513: * &schar if name is in system space 7514: * flag = 0 if name is sought 7515: * 1 if name is to be created 7516: * 2 if name is to be deleted 7517: */ 7518: namei(func, flag) 7519: int (*func)(); 7520: { 7521: register struct inode *dp; 7522: register c; 7523: register char *cp; 7524: int eo, *bp; 7525: 7526: /* 7527: * If name starts with '/' start from 7528: * root; otherwise start from current dir. 7529: */ 7530: 7531: dp = u.u_cdir; 7532: if((c=(*func)()) == '/') 7533: dp = rootdir; 7534: iget(dp->i_dev, dp->i_number); 7535: while(c == '/') 7536: c = (*func)(); 7537: if(c == '\0' && flag != 0) { 7538: u.u_error = ENOENT; 7539: goto out; 7540: } 7541: 7542: cloop: 7543: /* 7544: * Here dp contains pointer 7545: * to last component matched. 7546: */ 7547: 7548: if(u.u_error) 7549: goto out; 7550: if(c == '\0') 7551: return(dp); 7552: 7553: /* 7554: * If there is another component, 7555: * dp must be a directory and 7556: * must have x permission. 7557: */ 7558: 7559: if((dp->i_mode&IFMT) != IFDIR) { 7560: u.u_error = ENOTDIR; 7561: goto out; 7562: } 7563: if(access(dp, IEXEC)) 7564: goto out; 7565: 7566: /* Gather up name into 7567: * users' dir buffer. 7568: */ 7569: 7570: cp = &u.u_dbuf[0]; 7571: while(c!='/' && c!='\0' && u.u_error==0) { 7572: if(cp < &u.u_dbuf[DIRSIZ]) 7573: *cp++ = c; 7574: c = (*func)(); 7575: } 7576: while(cp < &u.u_dbuf[DIRSIZ]) 7577: *cp++ = '\0'; 7578: while(c == '/') 7579: c = (*func)(); 7580: if(u.u_error) 7581: goto out; 7582: 7583: /* Set up to search a directory. */ 7584: 7585: u.u_offset[1] = 0; 7586: u.u_offset[0] = 0; 7587: u.u_segflg = 1; 7588: eo = 0; 7589: u.u_count = ldiv(dp->i_size1, DIRSIZ+2); 7590: bp = NULL; 7591: 7592: eloop: 7593: 7594: /* 7595: * If at the end of the directory, 7596: * the search failed. Report what 7597: * is appropriate as per flag. 7598: */ 7599: 7600: if(u.u_count == 0) { 7601: if(bp != NULL) 7602: brelse(bp); 7603: if(flag==1 && c=='\0') { 7604: if(access(dp, IWRITE)) 7605: goto out; 7606: u.u_pdir = dp; 7607: if(eo) 7608: u.u_offset[1] = eo-DIRSIZ-2; else 7609: dp->i_flag =| IUPD; 7610: return(NULL); 7611: } 7612: u.u_error = ENOENT; 7613: goto out; 7614: } 7615: 7616: /* 7617: * If offset is on a block boundary, 7618: * read the next directory block. 7619: * Release previous if it exists. 7620: */ 7621: 7622: if((u.u_offset[1]&0777) == 0) { 7623: if(bp != NULL) 7624: brelse(bp); 7625: bp = bread(dp->i_dev, 7626: bmap(dp, ldiv(u.u_offset[1], 512))); 7627: } 7628: 7629: /* Note first empty directory slot 7630: * in eo for possible creat. 7631: * String compare the directory entry 7632: * and the current component. 7633: * If they do not match, go back to eloop. 7634: */ 7635: 7636: bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2); 7637: 7638: u.u_offset[1] =+ DIRSIZ+2; 7639: u.u_count--; 7640: if(u.u_dent.u_ino == 0) { 7641: if(eo == 0) 7642: eo = u.u_offset[1]; 7643: goto eloop; 7644: } 7645: for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++) 7646: if(*cp != cp[u.u_dent.u_name - u.u_dbuf]) 7647: goto eloop; 7648: 7649: 7650: /* Here a component matched in a directory. 7651: * If there is more pathname, go back to 7652: * cloop, otherwise return. 7653: */ 7654: 7655: if(bp != NULL) 7656: brelse(bp); 7657: if(flag==2 && c=='\0') { 7658: if(access(dp, IWRITE)) 7659: goto out; 7660: return(dp); 7661: } 7662: bp = dp->i_dev; 7663: iput(dp); 7664: dp = iget(bp, u.u_dent.u_ino); 7665: if(dp == NULL) 7666: return(NULL); 7667: goto cloop; 7668: 7669: out: 7670: iput(dp); 7671: return(NULL); 7672: } 7673: /* --------------------------- */ 7674: 7675: /* 7676: * Return the next character from the 7677: * kernel string pointed at by dirp. 7678: */ 7679: schar() 7680: { 7681: 7682: return(*u.u_dirp++ & 0377); 7683: } 7684: /* --------------------------- */ 7685: 7686: /* Return the next character from the 7687: * user string pointed at by dirp. 7688: */ 7689: uchar() 7690: { 7691: register c; 7692: 7693: c = fubyte(u.u_dirp++); 7694: if(c == -1) 7695: u.u_error = EFAULT; 7696: return(c); 7697: } 7698: /* --------------------------- */