360 Project HELP

READ chapter 11.9.4

                      HOW TO read

int read_file()
{
  Preparations: 
    ASSUME: file is opened for RD or RW;  e.g. fd = 0 opened for READ
    ask for a fd  and  nbytes to read;    e.g. read 0 10; read 0 123
		      
    verify fd is indeed opened for RD or RW;
    return myread(fd, buf, nbytes);
}

int myread(int fd, char buf[ ], nbytes) behaves EXACTLY the same as the
      read() system call in Unix/Linux.
		      
The algorithm of myread() can be best explained in terms of the following 
diagram.

(1).  PROC              (2).                          | 
     =======   |--> OFT oft[ ]                        |
     | pid |   |   ==============                     |
     | cwd |   |   |mode=flags  |                     | 
     | . ..|   |   |minodeptr ------->  minode[ ]     |      BlockDevice
     | fd[]|   |   |shareCount=1|     =============   |   ==================
 fd: | .------>|   |offset      |     |  INODE    |   |   | INODE -> blocks|
     |     |       |===|========|     |-----------|   |   ==================
     =======           |              |  dev,ino  |   |
                       |              =============   |
                       |
                       |<------- avil ------->|
    -------------------|-----------------------
    |    |    | ...  |lbk  |   |  ...| .......|
    -------------------|---|------------------|-
lbk   0    1 .....   | |rem|                   |
                     start                   fsize  
                        
------------------------------------------------------------------------------
                 Data structures for reading file

(1). Assume that fd is opened for READ. 
(2). The offset in the OFT points to the current byte position in the file from
     where we wish to read nbytes. 
(3). To the kernel, a file is just a sequence of contiguous bytes, numbered from
     0 to file_size - 1. As the figure shows, the current byte position, offset
     falls in a LOGICAL block (lbk), which is 

             lbk = offset / BLKSIZE 

     the byte to start read in that logical block is 

             start = offset % BLKSIZE 

     and the number of bytes remaining in the logical block is 

             remain = BLKSIZE - start. 

     At this moment, the file has 

             avil = file_size - offset 

     bytes available for read. 

     These numbers are used in the read algorithm.


(4). myread() behaves exactly the same as the read(fd, buf, nbytes) syscall of 
     Unix/Linux. It tries to read nbytes from fd to buf[ ], and return the 
     actual number of bytes read.

(5). ============ Algorithm and pseudo-code of myread() =======================

int myread(int fd, char *buf, int nbytes)
{
 1. int count = 0;
    avil = fileSize - OFT's offset // number of bytes still available in file.
    char *cq = buf;                // cq points at buf[ ]

 2. while (nbytes && avil){

       Compute LOGICAL BLOCK number lbk and startByte in that block from offset;

             lbk       = oftp->offset / BLKSIZE;
             startByte = oftp->offset % BLKSIZE;
     
       // I only show how to read DIRECT BLOCKS. YOU do INDIRECT and D_INDIRECT
 
       if (lbk < 12){                     // lbk is a direct block
           blk = mip->INODE.i_block[lbk]; // map LOGICAL lbk to PHYSICAL blk
       }
       else if (lbk >= 12 && lbk < 256 + 12) { 
            //  indirect blocks 
       }
       else{ 
            //  double indirect blocks
       } 

       /* get the data block into readbuf[BLKSIZE] */
       get_block(mip->dev, blk, readbuf);

       /* copy from startByte to buf[ ], at most remain bytes in this block */
       char *cp = readbuf + startByte;   
       remain = BLKSIZE - startByte;   // number of bytes remain in readbuf[]

       while (remain > 0){
            *cq++ = *cp++;             // copy byte from readbuf[] into buf[]
             oftp->offset++;           // advance offset 
             count++;                  // inc count as number of bytes read
             avil--; nbytes--;  remain--;
             if (nbytes <= 0 || avil <= 0) 
                 break;
       }
 
       // if one data block is not enough, loop back to OUTER while for more ...

   }
   printf("myread: read %d char from file descriptor %d\n", count, fd);  
   return count;   // count is the actual number of bytes read
}

                  OPTMIAZATION OF THE READ CODE:

Instead of reading one byte at a time and updating the counters on each byte,
TRY to make the read loops more efficient by reading a max chunck of data at a
time (and adjust the counters accordingly). 

REQUIRED: optimize the read algorithm in your project.

==========================  HOW TO cat ======================================
cat filename:

   char mybuf[1024], dummy = 0;  // a null char at end of mybuf[ ]
   int n;

1. int fd = open filename for READ;

2. while( n = read(fd, mybuf[1024], 1024)){
       mybuf[n] = 0;             // as a null terminated string
       // printf("%s", mybuf);   <=== THIS works but not good
       spit out chars from mybuf[ ] but handle \n properly;
   } 
3. close(fd);