360 PROJECT HELP

READ Chapter 11.9.5

                     HOW TO write_cp

int write_file()
{
  1. Preprations:
     ask for a fd   and   a text string to write;

e.g.     write 1 1234567890;    write 1 abcdefghij

		     
  2. verify fd is indeed opened for WR or RW or APPEND mode

  3. copy the text string into a buf[] and get its length as nbytes.

     return mywrite(fd, buf, nbytes);
}

The algorithm of write_file() can also be explained in terms of the following
figure.

(1).  PROC              (2).                          | 
     =======   |--> OFT oft[ ]                        |
     | pid |   |   =============                      |
     | cwd |   |   |mode=flags |                      | 
     | . ..|   |   |minodePtr ------>  minode[ ]      |      BlockDevice
     | fd[]|   |   |sharCount=1|     =============    |   ==================
 fd: | .------>|   |offset     |     |  INODE    |    |   | INODE -> blocks|
     |     |       |===|=======|     |-----------|    |   ==================
     =======           |             | dev,ino   |    | 
                       |             | modified  |    |
                       |             =============    |
                       |
    -------------------|-----------------
    |    |    | ...  |lbk  | ............
    -------------------|-----------------
lbk   0    1 .....     |rem|            |
                     start           fileSize (in INODE)  
                        
------------------------------------------------------------------------------
               Data Structures for write()


mywrite behaves exactly the same as Unix's write(fd, buf, nbytes) syscall.
It writes nbytes from buf[ ] to the file descriptor fd, extending the file 
size as needed.

int mywrite(int fd, char buf[ ], int nbytes) 
{
  while (nbytes > 0 ){

     compute LOGICAL BLOCK (lbk) and the startByte in that lbk:

          lbk       = oftp->offset / BLKSIZE;
          startByte = oftp->offset % BLKSIZE;

    // I only show how to write DIRECT data blocks, you figure out how to 
    // write indirect and double-indirect blocks.

     if (lbk < 12){                         // direct block
        if (ip->INODE.i_block[lbk] == 0){   // if no data block yet

           mip->INODE.i_block[lbk] = balloc(mip->dev);// MUST ALLOCATE a block
        }
        blk = mip->INODE.i_block[lbk];      // blk should be a disk block now
     }

  
     else if (lbk >= 12 && lbk < 256 + 12){ // INDIRECT blocks 
          // HELP INFO:
           if (i_block[12] == 0){
              allocate a block for it;
              zero out the block on disk !!!!
           }
           get i_block[12] into an int ibuf[256];
           blk = ibuf[lbk - 12];
           if (blk==0){
               allocate a disk block;
               record it in ibuf[lbk - 12];
           }
           write ibuf[ ] back to disk block i_block[12];
     }

     /*******************************************************************
             linear lbk to double indirect block blk mapping:

     |0...12|13...267|268 ....|.......|.......| ..........      
     |Direct|Indirect|0       |       |       | ..........
        12     256    |  256     256     256 
                      |
                      ^
                  lbk-12-256
        --------------------------------------------------
         lbk -= (12+256);    // lbk begins from 0 
         lbk / 256;          // which double indirect block
         lbk % 256;          // which entry in that block 
     *******************************************************************/

     else{
            // double indirect blocks */
     }

     /* all cases come to here : write to the data block */
     get_block(mip->dev, blk, wbuf);   // read disk block into wbuf[ ]  
     char *cp = wbuf + startByte;      // cp points at startByte in wbuf[]
     remain = BLKSIZE - startByte;     // number of BYTEs remain in this block

     while (remain > 0){               // write as much as remain allows  
           *cp++ = *cq++;              // cq points at buf[ ]
           nbytes--; remain--;         // dec counts
           oftp->offset++;             // advance offset
           if (offset > INODE.i_size)  // especially for RW|APPEND mode
               mip->INODE.i_size++;    // inc file size (if offset > fileSize)
           if (nbytes <= 0) break;     // if already nbytes, break
     }
     put_block(mip->dev, blk, wbuf);   // write wbuf[ ] to disk
     
     // loop back to outer while to write more .... until nbytes are written
  }

  mip->dirty = 1;       // mark mip dirty for iput() 
  printf("wrote %d char into file descriptor fd=%d\n", nbytes, fd);           
  return nbytes;
}


                OPTIMIZATION OF write Code

As in read(), the above inner while(remain > 0) loop can be optimized:
Instead of copying one byte at a time and update the control variables on each 
byte, TRY to copy only ONCE and adjust the control variables accordingly.

REQUIRED: Optimize the write() code in your project.

=============================================================================

                      HOW TO cp ONE file:

cp src dest:

1. fd = open src for READ;

2. gd = open dst for WR|CREAT; 

NOTE: In the project, if dst for WRITE does not exist, your open() should
      creat the dst file first, then open it for WRITE
	

3. while( n=read(fd, buf[ ], BLKSIZE) ){
       write(gd, buf, n);  // notice the n in write()
   }

==============================================================================

                    HOW TO mv (rename)
mv src dest:

1. verify src exists; get its INODE in ==> you already know its dev
2. check whether src is on the same dev as src

              CASE 1: same dev:
3. Hard link dst with src (i.e. same INODE number)
4. unlink src (i.e. rm src name from its parent directory and reduce INODE's
               link count by 1).
                
              CASE 2: not the same dev:
3. cp src to dst
4. unlink src
==============================================================================

How to head file: Linux head prints the FIRST 10 lines of a file

1. open the file for READ;
2. read BLKSIZE into char buf[ ] = |abcd..\n1234...\nxyzw...\n....
                                    |
	                      char *cp
	
3. scan buf[ ] for \n; For each \n: lines++ until 10; add a 0 after LAST \n

4. print buf as %s

=============================================================================

HOW to tail file: Linux tail prints LAST 10 lines of a file

1. open file fore READ;
2. get file_size (in its INODE.i_size)
3. lssek to (file_size - BLKSIZE)      (OR to 0 if file_size < BLKSIZE)
								       
							       n 	
4. n = read BLKSIZE into buf[ ]=|............abc\n1234\nlast\n|0|
                                                               |
                                                        char *cp
							
5. scan buf[ ] backwards for \n;  lines++  until lines=11
6. print from cp+1 as %s
============================================================================