/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { // First retrieve the inode in question struct inode node; int inode_iget_status = inode_iget(fs, inumber, &node); if (inode_iget_status == -1) return -1; // Then we want to get the block int block = inode_indexlookup(fs, &node, blockNum); if (!block) return -1; // Now retrive the contents of the block and put it into the buffer int sector_status = diskimg_readsector(fs->dfd, block, buf); // Figure out what the size was supposed to be int inodesize = inode_getsize(&node); // Now figure out what the valid number of bytes to return is int bytesRemaining = inodesize - blockNum * 512; if (bytesRemaining < 512) { return bytesRemaining; } return sector_status; }
/* * Allocate and initialize a struct unixfilesystem give a open disk image. * Return NULL on error. */ struct unixfilesystem * unixfilesystem_init(int dfd) { /* validate the bootblock. Hopefully this will catch passing * something other than a diskimg to us. */ uint16_t bootblock[256]; if (diskimg_readsector(dfd, BOOTBLOCK_SECTOR, bootblock) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Error reading bootblock\n"); return NULL; } if (bootblock[0] != BOOTBLOCK_MAGIC_NUM) { fprintf(stderr, "Bad magic number on disk(0x%x)\n", bootblock[0]); return NULL; } if (sizeof(struct filsys) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Warning: Superblock structure size (%zu) != SECTOR_SIZE\n", sizeof(struct filsys)); } struct unixfilesystem *fs = malloc(sizeof(struct unixfilesystem)); if (fs == NULL) { fprintf(stderr,"Out of memory.\n"); return NULL; } fs->dfd = dfd; /* read superblock */ if (diskimg_readsector(dfd, SUPERBLOCK_SECTOR, &(fs->superblock)) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Error reading superblock\n"); free(fs); return NULL; } return fs; }
/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { //fprintf(stderr, "in file_getblock, size %d, inum: %d\n", cacheMemSizeInKB, inumber); struct inode in; int getResult = inode_iget(fs, inumber, &in); int sectorNum = inode_indexlookup(fs, &in, blockNum); int bytesRead = diskimg_readsector(fs->dfd, sectorNum, buf); if ((getResult == -1) || (bytesRead == -1) || (sectorNum == -1)) return -1; int size = inode_getsize(&in); if ((size % BYTES_PER_BLOCK) == 0) { return BYTES_PER_BLOCK; } else { int numblocks = (size / BYTES_PER_BLOCK); if (blockNum == numblocks) { return size % BYTES_PER_BLOCK; } else { return BYTES_PER_BLOCK; } } }
/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { // Consider inumber = 17, blocknumber = 5: // – Find the inode struct inode inp; if(inode_iget(fs, inumber, &inp) < 0){ printf("Error getting inode %i\n", inumber); return -1; } int filesize = inode_getsize(&inp); int partial = (filesize % DISKIMG_SECTOR_SIZE == 0) ? 0 : 1; int blocks = (filesize / DISKIMG_SECTOR_SIZE) + partial; // – Find the sector number int sectorNum = inode_indexlookup(fs, &inp, blockNum); if(sectorNum == -1){ printf("Error getting data sector %i\n", blockNum); return -1; } if((sectorNum > (int)fs->superblock.s_fsize) || (sectorNum < fs->superblock.s_isize + INODE_START_SECTOR)){ printf("sectorNum: %i blockNum: %i blocks: %i inode: %i\n", sectorNum, blockNum, blocks, inumber); } // – Read the data in the sector into the buffer if (diskimg_readsector(fs->dfd, sectorNum, buf) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Error reading sector %i for block %i of %i\n", sectorNum, blockNum, blocks); return -1; } //Determine value of valid bytes in the block if(blockNum == blocks - 1){ if(partial) { return (filesize % DISKIMG_SECTOR_SIZE); }else{ return DISKIMG_SECTOR_SIZE; } }else{ return DISKIMG_SECTOR_SIZE; } }
/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { //Find the inode struct inode inp; if(inode_iget(fs, inumber, &inp) < 0){ printf("Error getting inode %i\n", inumber); return -1; } //Find the sector number for the blockNum int sectorNum = inode_indexlookup(fs, &inp, blockNum); if(sectorNum == -1){ printf("Error getting data sector %i\n", blockNum); return -1; } //Read the data in the sector into the buffer if (diskimg_readsector(fs->dfd, sectorNum, buf) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Error reading sector %i for block %i\n", sectorNum, blockNum); return -1; } //Return number of valid bytes in the block return validBytes(&inp, blockNum); }