6400: #
6401: #include "../param.h"
6402: #include "../conf.h"
6403: #include "../inode.h"
6404: #include "../user.h"
6405: #include "../buf.h"
6406: #include "../systm.h"
6407: 
6408: /* Bmap defines the structure of file system storage
6409:  * by returning the physical block number on a device given the
6410:  * inode and the logical block number in a file.
6411:  * When convenient, it also leaves the physical
6412:  * block number of the next block of the file in rablock
6413:  * for use in read-ahead.
6414:  */
6415: bmap(ip, bn)
6416: struct inode *ip;
6417: int bn;
6418: {
6419:         register *bp, *bap, nb;
6420:         int *nbp, d, i;
6421: 
6422:         d = ip->i_dev;
6423:         if(bn & ~077777) {
6424:                 u.u_error = EFBIG;
6425:                 return(0);
6426:         }
6427:         if((ip->i_mode&ILARG) == 0) {
6428: 
6429:                 /* small file algorithm */
6430: 
6431:                 if((bn & ~7) != 0) {
6432: 
6433:                         /* convert small to large */
6434: 
6435:                         if ((bp = alloc(d)) == NULL)
6436:                                 return(NULL);
6437:                         bap = bp->b_addr;
6438:                         for(i=0; i<8; i++) {
6439:                                 *bap++ = ip->i_addr[i];
6440:                                 ip->i_addr[i] = 0;
6441:                         }
6442:                         ip->i_addr[0] = bp->b_blkno;
6443:                         bdwrite(bp);
6444:                         ip->i_mode =| ILARG;
6445:                         goto large;
6446:                 }
6447:                 nb = ip->i_addr[bn];
6448:                 if(nb == 0 && (bp = alloc(d)) != NULL) {
6449:                         bdwrite(bp);
6450:                         nb = bp->b_blkno;
6451:                         ip->i_addr[bn] = nb;
6452:                         ip->i_flag =| IUPD;
6453:                 }
6454:                 rablock = 0;
6455:                 if (bn<7)
6456:                         rablock = ip->i_addr[bn+1];
6457:                 return(nb);
6458:         }
6459: 
6460:         /* large file algorithm */
6461: 
6462:     large:
6463:         i = bn>>8;
6464:         if(bn & 0174000)
6465:                 i = 7;
6466:         if((nb=ip->i_addr[i]) == 0) {
6467:                 ip->i_flag =| IUPD;
6468:                 if ((bp = alloc(d)) == NULL)
6469:                         return(NULL);
6470:                 ip->i_addr[i] = bp->b_blkno;
6471:         } else
6472:                 bp = bread(d, nb);
6473:         bap = bp->b_addr;
6474: 
6475:         /* "huge" fetch of double indirect block */
6476: 
6477:         if(i == 7) {
6478:                 i = ((bn>>8) & 0377) - 7;
6479:                 if((nb=bap[i]) == 0) {
6480:                         if((nbp = alloc(d)) == NULL) {
6481:                                 brelse(bp);
6482:                                 return(NULL);
6483:                         }
6484:                         bap[i] = nbp->b_blkno;
6485:                         bdwrite(bp);
6486:                 } else {
6487:                         brelse(bp);
6488:                         nbp = bread(d, nb);
6489:                 }
6490:                 bp = nbp;
6491:                 bap = bp->b_addr;
6492:         }
6493: 
6494:         /* normal indirect fetch */
6495: 
6496:         i = bn & 0377;
6497:         if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) {
6498:                 nb = nbp->b_blkno;
6499:                 bap[i] = nb;
6500:                 bdwrite(nbp);
6501:                 bdwrite(bp);
6502:         } else
6503:                 brelse(bp);
6504:         rablock = 0;
6505:         if(i < 255)
6506:                 rablock = bap[i+1];
6507:         return(nb);
6508: }
6509: /* ---------------------------       */
6510: 
6511: /*
6512:  * Pass back  c  to the user at his location u_base;
6513:  * update u_base, u_count, and u_offset.  Return -1
6514:  * on the last character of the user's read.
6515:  * u_base is in the user address space unless u_segflg is set.
6516:  */
6517: passc(c)
6518: char c;
6519: {
6520: 
6521:         if(u.u_segflg)
6522:                 *u.u_base = c; else
6523:                 if(subyte(u.u_base, c) < 0) {
6524:                         u.u_error = EFAULT;
6525:                         return(-1);
6526:                 }
6527:         u.u_count--;
6528:         if(++u.u_offset[1] == 0)
6529:                 u.u_offset[0]++;
6530:         u.u_base++;
6531:         return(u.u_count == 0? -1: 0);
6532: }
6533: /* ---------------------------       */
6534: 
6535: /*
6536:  * Pick up and return the next character from the user's
6537:  * write call at location u_base;
6538:  * update u_base, u_count, and u_offset.  Return -1
6539:  * when u_count is exhausted.  u_base is in the user's
6540:  * address space unless u_segflg is set.
6541:  */
6542: cpass()
6543: {
6544:         register c;
6545: 
6546:         if(u.u_count == 0)
6547:                 return(-1);
6548:         if(u.u_segflg)
6549:                 c = *u.u_base; else
6550:                 if((c=fubyte(u.u_base)) < 0) {
6551:                         u.u_error = EFAULT;
6552:                         return(-1);
6553:                 }
6554:         u.u_count--;
6555:         if(++u.u_offset[1] == 0)
6556:                 u.u_offset[0]++;
6557:         u.u_base++;
6558:         return(c&0377);
6559: }
6560: /* ---------------------------       */
6561: 
6562: /*
6563:  * Routine which sets a user error; placed in
6564:  * illegal entries in the bdevsw and cdevsw tables.
6565:  */
6566: nodev()
6567: {
6568: 
6569:         u.u_error = ENODEV;
6570: }
6571: /* ---------------------------       */
6572: 
6573: /*
6574:  * Null routine; placed in insignificant entries
6575:  * in the bdevsw and cdevsw tables.
6576:  */
6577: nulldev()
6578: {
6579: }
6580: /* ---------------------------       */
6581: 
6582: /*
6583:  * copy count words from from to to.
6584:  */
6585: bcopy(from, to, count)
6586: int *from, *to;
6587: {
6588:         register *a, *b, c;
6589: 
6590:         a = from;
6591:         b = to;
6592:         c = count;
6593:         do
6594:                 *b++ = *a++;
6595:         while(--c);
6596: }
6597: /* ---------------------------       */