07550 #include "../h/param.h" 07551 #include "../h/systm.h" 07552 #include "../h/conf.h" 07553 #include "../h/inode.h" 07554 #include "../h/dir.h" 07555 #include "../h/user.h" 07556 #include "../h/buf.h" 07557 07558 /* 07559 * Bmap defines the structure of file system storage 07560 * by returning the physical block number on a device given the 07561 * inode and the logical block number in a file. 07562 * When convenient, it also leaves the physical 07563 * block number of the next block of the file in rablock 07564 * for use in read-ahead. 07565 */ 07566 daddr_t 07567 bmap(ip, bn, rwflg) 07568 register struct inode *ip; 07569 daddr_t bn; 07570 { 07571 register i; 07572 struct buf *bp, *nbp; 07573 int j, sh; 07574 daddr_t nb, *bap; 07575 dev_t dev; 07576 07577 if(bn < 0) { 07578 u.u_error = EFBIG; 07579 return((daddr_t)0); 07580 } 07581 dev = ip->i_dev; 07582 rablock = 0; 07583 07584 /* 07585 * blocks 0..NADDR-4 are direct blocks 07586 */ 07587 if(bn < NADDR-3) { 07588 i = bn; 07589 nb = ip->i_un.i_addr[i]; 07590 if(nb == 0) { 07591 if(rwflg==B_READ || (bp = alloc(dev))==NULL) 07592 return((daddr_t)-1); 07593 nb = bp->b_blkno; 07594 bdwrite(bp); 07595 ip->i_un.i_addr[i] = nb; 07596 ip->i_flag |= IUPD|ICHG; 07597 } 07598 if(i < NADDR-4) 07599 rablock = ip->i_un.i_addr[i+1]; 07600 return(nb); 07601 } 07602 07603 /* 07604 * addresses NADDR-3, NADDR-2, and NADDR-1 07605 * have single, double, triple indirect blocks. 07606 * the first step is to determine 07607 * how many levels of indirection. 07608 */ 07609 sh = 0; 07610 nb = 1; 07611 bn -= NADDR-3; 07612 for(j=3; j>0; j--) { 07613 sh += NSHIFT; 07614 nb <<= NSHIFT; 07615 if(bn < nb) 07616 break; 07617 bn -= nb; 07618 } 07619 if(j == 0) { 07620 u.u_error = EFBIG; 07621 return((daddr_t)0); 07622 } 07623 07624 /* 07625 * fetch the address from the inode 07626 */ 07627 nb = ip->i_un.i_addr[NADDR-j]; 07628 if(nb == 0) { 07629 if(rwflg==B_READ || (bp = alloc(dev))==NULL) 07630 return((daddr_t)-1); 07631 nb = bp->b_blkno; 07632 bdwrite(bp); 07633 ip->i_un.i_addr[NADDR-j] = nb; 07634 ip->i_flag |= IUPD|ICHG; 07635 } 07636 07637 /* 07638 * fetch through the indirect blocks 07639 */ 07640 for(; j<=3; j++) { 07641 bp = bread(dev, nb); 07642 if(bp->b_flags & B_ERROR) { 07643 brelse(bp); 07644 return((daddr_t)0); 07645 } 07646 bap = bp->b_un.b_daddr; 07647 sh -= NSHIFT; 07648 i = (bn>>sh) & NMASK; 07649 nb = bap[i]; 07650 if(nb == 0) { 07651 if(rwflg==B_READ || (nbp = alloc(dev))==NULL) { 07652 brelse(bp); 07653 return((daddr_t)-1); 07654 } 07655 nb = nbp->b_blkno; 07656 bdwrite(nbp); 07657 bap[i] = nb; 07658 bdwrite(bp); 07659 } else 07660 brelse(bp); 07661 } 07662 07663 /* 07664 * calculate read-ahead. 07665 */ 07666 if(i < NINDIR-1) 07667 rablock = bap[i+1]; 07668 return(nb); 07669 } 07670 07671 /* 07672 * Pass back c to the user at his location u_base; 07673 * update u_base, u_count, and u_offset. Return -1 07674 * on the last character of the user's read. 07675 * u_base is in the user address space unless u_segflg is set. 07676 */ 07677 passc(c) 07678 register c; 07679 { 07680 register id; 07681 07682 if((id = u.u_segflg) == 1) 07683 *u.u_base = c; 07684 else 07685 if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) { 07686 u.u_error = EFAULT; 07687 return(-1); 07688 } 07689 u.u_count--; 07690 u.u_offset++; 07691 u.u_base++; 07692 return(u.u_count == 0? -1: 0); 07693 } 07694 07695 /* 07696 * Pick up and return the next character from the user's 07697 * write call at location u_base; 07698 * update u_base, u_count, and u_offset. Return -1 07699 * when u_count is exhausted. u_base is in the user's 07700 * address space unless u_segflg is set. 07701 */ 07702 cpass() 07703 { 07704 register c, id; 07705 07706 if(u.u_count == 0) 07707 return(-1); 07708 if((id = u.u_segflg) == 1) 07709 c = *u.u_base; 07710 else 07711 if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) { 07712 u.u_error = EFAULT; 07713 return(-1); 07714 } 07715 u.u_count--; 07716 u.u_offset++; 07717 u.u_base++; 07718 return(c&0377); 07719 } 07720 07721 /* 07722 * Routine which sets a user error; placed in 07723 * illegal entries in the bdevsw and cdevsw tables. 07724 */ 07725 nodev() 07726 { 07727 07728 u.u_error = ENODEV; 07729 } 07730 07731 /* 07732 * Null routine; placed in insignificant entries 07733 * in the bdevsw and cdevsw tables. 07734 */ 07735 nulldev() 07736 { 07737 } 07738 07739 /* 07740 * copy count bytes from from to to. 07741 */ 07742 bcopy(from, to, count) 07743 caddr_t from, to; 07744 register count; 07745 { 07746 register char *f, *t; 07747 07748 f = from; 07749 t = to; 07750 do 07751 *t++ = *f++; 07752 while(--count); 07753 } 07754 07755 07756 07757 07758 07759 07760 07761 07762 07763 07764 07765 07766 07767 07768 07769 07770 07771 07772 07773 07774 07775 07776 07777 07778 07779 07780 07781 07782 07783 07784 07785 07786 07787 07788 07789 07790 07791 07792 07793 07794 07795 07796 07797 07798 07799