nami.c

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 /* 7630 * Note first empty directory slot 7631 * in eo for possible creat. 7632 * String compare the directory entry 7633 * and the current component. 7634 * If they do not match, go back to eloop. 7635 */ 7636 7637 bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2); 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 /* ------------------------ */ 7699