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
============================================================================