Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include "ext2.h"
- #include <errno.h>
- #include <string.h>
- #include <assert.h>
- #include <stdlib.h>
- /* Given an i-node and a logical block number, this function looks up the corresponding
- physical block number, and obtains a reference to the block via the buffer cache. */
- int get_inode_block(inode *ino, uint32_t lblock, int alloc, buffer **buf)
- {
- /* calculate references per block */
- uint32_t rpb = ino->fs->blocksize / 4;
- buffer *tempbuf; /* will point to buffer object */
- tempbuf = (buffer *)malloc(sizeof(buffer));
- int r; /* error code */
- /* Access method: Direct */
- if (lblock < 12) {
- if (0 > (r = bufcache_get(ino->fs->bc,ino->in.block[lblock],buf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- return 0;
- }
- /* Access method: Triple Indirect */
- if (lblock >= (rpb*rpb + rpb + 12)) {
- uint32_t pblock = ino->in.block[14];
- int tripoffset = (lblock-12-rpb-rpb*rpb)/(rpb*rpb);
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,&tempbuf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- memcpy(&pblock,&tempbuf->data[tripoffset*4],4);
- bufcache_release(ino->fs->bc,tempbuf,0);
- int douboffset = ((lblock-12-rpb-rpb*rpb)/rpb)%rpb;
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,&tempbuf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- memcpy(&pblock,&tempbuf->data[douboffset*4],4);
- bufcache_release(ino->fs->bc,tempbuf,0);
- int singoffset = (lblock-12-rpb-rpb*rpb)%rpb;
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,&tempbuf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- memcpy(&pblock,&tempbuf->data[singoffset*4],4);
- bufcache_release(ino->fs->bc,tempbuf,0);
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,buf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- return 0;
- }
- /* Access method: Double Indirect */
- if (lblock >= rpb + 12) {
- uint32_t pblock = ino->in.block[13];
- int douboffset = (lblock-12-rpb)/rpb;
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,&tempbuf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- memcpy(&pblock,&tempbuf->data[douboffset*4],4);
- bufcache_release(ino->fs->bc,tempbuf,0);
- int singoffset = (lblock-12-rpb)%rpb;
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,&tempbuf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- memcpy(&pblock,&tempbuf->data[singoffset*4],4);
- bufcache_release(ino->fs->bc,tempbuf,0);
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,buf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- return 0;
- }
- /* Access method: Single Indirect */
- uint32_t pblock = ino->in.block[12];
- int singoffset = lblock - 12;
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,&tempbuf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- memcpy(&pblock,&tempbuf->data[singoffset*4],4);
- bufcache_release(ino->fs->bc,tempbuf,0);
- if (0 > (r = bufcache_get(ino->fs->bc,pblock,buf))) {
- /* perform any necessary cleanup */
- return r; /* notify caller of error */
- }
- return 0;
- }
- /* Corresponds to the read system call, as described in the manpage (man 2 read). The
- only two differences with this function is that it also takes an offset as a parameter, and
- uses an i-node object to indicate the file to read from, instead of a file descriptor. */
- ssize_t ext2_read(inode *ino, void *buf, off_t start, size_t len)
- {
- int size = ino->in.size;
- buffer *tempbuf;
- if (start >= size) {
- return 0;
- }
- /* calculate logical block */
- uint32_t lblockcounter = start/ino->fs->blocksize;
- int lefttoread = size - start;
- /* check to see the length limitation */
- if (lefttoread > len) {
- lefttoread = len;
- }
- int amountreaditer, amountreadtotal = 0;
- /* if start is non-zero then the first read is going to start from an offset */
- if (start%ino->fs->blocksize && lefttoread > 0) {
- /* fetch physical block */
- get_inode_block(ino, lblockcounter, 0, &tempbuf);
- /* set amount to be read this iteration */
- amountreaditer = ino->fs->blocksize - (start%ino->fs->blocksize);
- /* increase amount read and decrement amount left to read */
- amountreadtotal += amountreaditer;
- lefttoread -= amountreaditer;
- /* copy chunk of data into the buffer and increase the buffer position */
- memcpy(buf, tempbuf->data + start%ino->fs->blocksize, amountreaditer);
- buf = ((uint8_t *)buf) + amountreaditer;
- /* release resources and fetch next logical block */
- bufcache_release(ino->fs->bc,tempbuf,0);
- lblockcounter++;
- }
- /* continue reading blocks normally */
- while (lefttoread > 0) {
- /* fetch physical block */
- get_inode_block(ino, lblockcounter, 0, &tempbuf);
- /* check to see if the the current block is the last we need to read */
- if (lefttoread >= ino->fs->blocksize) {
- amountreaditer = ino->fs->blocksize;
- } else {
- /* set amount read this iteration */
- amountreaditer = lefttoread;
- }
- /* increase amount read and decrement amount left to read */
- amountreadtotal += amountreaditer;
- lefttoread -= amountreaditer;
- /* copy chunk of data into the buffer and increase the buffer position */
- memcpy(buf, tempbuf->data, amountreaditer);
- buf = ((uint8_t *)buf) + amountreaditer;
- /* release resources and fetch next logical block */
- bufcache_release(ino->fs->bc,tempbuf,0);
- lblockcounter++;
- }
- return amountreadtotal;
- }
- ssize_t ext2_write(inode *ino, const void *buf, off_t start, size_t len)
- {
- return -ENOSYS;
- }
- int ext2_truncate(inode *ino, off_t length)
- {
- return -ENOSYS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement