Exemple #1
0
/*
 * Read from an opend file. 
 * Read can not enlarge file. So you should not read outside the size of 
 * the file. If the read exceeds the file size, its result will be truncated.
 *
 * This function returns the number of bytes read.
 */
int sfs_read(int fd, void *buf, int length)
{
	int remaining, to_copy, offset;
	blkid *bids;
	int i, n;
	char *p = (char *)buf;
	char tmp[BLOCK_SIZE];
	u32 cur = fdtable[fd].cur;

	/* TODO: check if we need to truncate */
	if ((cur + length) > fdtable[fd].inode.size)
	{
		// Need to truncate, remove the last portion
		length = fdtable[fd].inode.size - length;
	}

	/* TODO: similar to the sfs_write() */
	// Get the block ids of content
	bids = malloc(length/BLOCK_SIZE + 1);
	n = sfs_get_file_content(bids, fd, cur, length);
	// Read operation
	remaining = length;
	offset = cur % BLOCK_SIZE;
	if (BLOCK_SIZE - offset > remaining)
	{
		to_copy = remaining;
	}
	else
	{
		to_copy = BLOCK_SIZE - offset;
	}

	for (i = 0; i < n; i++)
	{
		sfs_read_block((char*)&tmp, bids[i]);
		memcpy(buf, tmp+offset, to_copy);
		remaining -= to_copy;
		offset = 0;
		if (remaining > BLOCK_SIZE)
		{
			to_copy = BLOCK_SIZE - offset;
		} else {
			to_copy = remaining;
		}
	}
 	// Update variables
	fdtable[fd].cur += length;

	free(bids);

	return length;
}
Exemple #2
0
/*
 * Read from an opened file. 
 * Read can not enlarge file. So you should not read outside the size of 
 * the file. If the read exceeds the file size, its result will be truncated.
 *
 * This function returns the number of bytes read.
 */
int sfs_read(int fd, void *buf, int length)
{
	int remaining, to_copy, offset;
	int frame_start, frame_end, content_blk, num_blocks;
	int i, n;
	char *p = (char *)buf;
	char inode_ptr[BLOCK_SIZE];
	char tmp[BLOCK_SIZE];
	u32 cur = fdtable[fd].cur;

	sfs_inode_t inode;
	sfs_read_block(inode_ptr, fdtable[fd].inode_bid);
	inode = *(sfs_inode_t*)inode_ptr;

	remaining = length;

	num_blocks = (length / BLOCK_SIZE) + 1; 
	blkid bids[num_blocks];

	//Find frame holding the cursor
	frame_start = cur / (SFS_FRAME_COUNT * BLOCK_SIZE);
	//Find the frame that would be holding the last byte we want to read
	frame_end = (cur + length) / (SFS_FRAME_COUNT * BLOCK_SIZE);

	int num_frames = frame_start - frame_end + 1;

	content_blk = cur / BLOCK_SIZE;
	offset = cur % BLOCK_SIZE;

	//Traverse the frames and check if the length exceeds the 
	//number of frames
	blkid frame_bid = inode.first_frame;
	sfs_inode_frame_t frame;

	int count = 0;
	int nonzero_block = 0;
	//Truncate file to the smallest BLOCK
	//The first and last blocks will have fewer bytes stored
	
	//Check frames to determine if all content blocks exist
	while(count < num_blocks){
		//Read the next frame
		sfs_read_block(tmp, frame_bid);
		frame = *(sfs_inode_frame_t*)tmp;
		frame_bid = frame.next;
		
		//Count the number of nonzero indices in the content array
		while(content_blk < SFS_FRAME_COUNT && count < num_blocks){
			if(frame.content[content_blk] != 0){
				nonzero_block++;
				count++;
				content_blk++;
			}
		}

		//Reset index to zero
		content_blk = 0;

		if(frame_bid == 0 && count < num_frames){
			printf("The specified length exceeds the file size.\n");
			break;
		}
	}

	//The length exceeds the number of valid blocks, truncate read
	if(count < num_blocks){
		//Add fewer bytes from first block
		remaining = BLOCK_SIZE - offset;
		num_blocks--;

		//Add the remaining blocks
		remaining = remaining + num_blocks * BLOCK_SIZE;

	} else{
		remaining = length;
	}

	/* TODO: similar to the sfs_write() */
	int num_content_blocks = sfs_get_file_content(bids, fd, cur, length);

	int bid_count = 0;
	char block_ptr[BLOCK_SIZE];
	
	while(remaining > 0){
		to_copy = 0;

		sfs_read_block(block_ptr, bids[bid_count]);

		//Case 1: Read block with offset
		if(offset != 0){
			
			//Partially fill block
			if(remaining < (BLOCK_SIZE - offset)){
				to_copy = remaining;
			} else{
				//Fill entire block
				to_copy = BLOCK_SIZE - offset;
			}

			strncpy(buf, block_ptr+offset, to_copy);
			offset = 0;

		} else if(remaining > BLOCK_SIZE){
			//Case 2: Write to a full block
			to_copy = BLOCK_SIZE;
			strncpy(buf, block_ptr, to_copy);

		} else{
			//Case 3: Write a partial block
			to_copy = remaining;
			strncpy(buf, block_ptr, to_copy);
		}

		remaining = remaining - to_copy;
		cur = cur + to_copy;
		fdtable[fd].cur = cur;
		
		bid_count++;
	}

	return length - remaining;
}
Exemple #3
0
/*
 * Write to a file. This function can potentially enlarge the file if the 
 * cur+length exceeds the size of file. Also you should be aware that the
 * cur may already be larger than the size (due to sfs_seek). In such
 * case, you will need to expand the file as well.
 * 
 * This function returns number of bytes written.
 */
int sfs_write(int fd, void *buf, int length)
{
	int remaining, offset, to_copy;
	char *p = (char *)buf;
	char tmp[BLOCK_SIZE];
	char inode_ptr[BLOCK_SIZE];
	u32 cur = fdtable[fd].cur;
	u32 buf_offset = 0;

	sfs_inode_t inode;
	remaining = length;
	offset = cur % BLOCK_SIZE;

	int numBids = (length / BLOCK_SIZE) + 1; 
	blkid bids[numBids];

	sfs_read_block(inode_ptr, fdtable[fd].inode_bid);
	inode = *(sfs_inode_t*)inode_ptr;
	blkid frame_bid = inode.first_frame;

	/* TODO: check if we need to resize */
	sfs_inode_frame_t frame;
	sfs_read_block(tmp, frame_bid);
	frame = *(sfs_inode_frame_t*)tmp;

	if( (length + cur) > inode.size){
		u32 new_size = length + cur;
		fdtable[fd].inode = inode;
		sfs_resize_file(fd, new_size);
	}

	/* TODO: get the block ids of all contents (using sfs_get_file_content() */
	int num_blocks = sfs_get_file_content(bids, fd, cur, length);

	/* TODO: main loop, go through every block, copy the necessary parts
	   to the buffer, consult the hint in the document. Do not forget to 
	   flush to the disk.
	*/

	char block_ptr[BLOCK_SIZE];
	int bid_count = 0;
	//The block numbers should already be known by this part
	while(remaining > 0){

		to_copy = 0;
		sfs_read_block(block_ptr, bids[bid_count]);

		//Case 1: Write to block with offset
		if(offset != 0){
			
			//Partially fill block
			if(remaining < (BLOCK_SIZE - offset)){
				to_copy = remaining;
			} else{
				//Fill entire block
				to_copy = BLOCK_SIZE - offset;
			}

			strncpy(block_ptr+offset, buf, to_copy);

			offset = 0;
		} else if(remaining > BLOCK_SIZE){
			//Case 2: Write to a full block
			to_copy = BLOCK_SIZE;
			strncpy(block_ptr, buf, to_copy);

		} else{
			//Case 3: Write a partial block
			to_copy = remaining;
			strncpy(block_ptr, buf, to_copy);
		}

		sfs_write_block(&block_ptr, bids[bid_count]);

		remaining = remaining - to_copy;
		cur = cur + to_copy;
		
		bid_count++;
	}

	fdtable[fd].cur = cur;

	return length - remaining;
}
Exemple #4
0
/*
 * Write to a file. This function can potentially enlarge the file if the 
 * cur+length exceeds the size of file. Also you should be aware that the
 * cur may already be larger than the size (due to sfs_seek). In such
 * case, you will need to expand the file as well.
 * 
 * This function returns number of bytes written.
 */
int sfs_write(int fd, void *buf, int length)
{
	int remaining, offset, to_copy;
	blkid *bids;
	int i, n;
	char *p = (char *)buf;
	char tmp[BLOCK_SIZE];
	u32 cur = fdtable[fd].cur;
	int frame_size, new_nframe, old_nframe;

	/* TODO: check if we need to resize */
	frame_size = BLOCK_SIZE * SFS_FRAME_COUNT;
	old_nframe =  (fdtable[fd].inode.size + frame_size-1)/frame_size;
	new_nframe = ((cur+length) + frame_size-1)/frame_size;

	if (new_nframe > old_nframe) 
	{
		// Need to allocate a new frame
		sfs_resize_file(fd, fdtable[fd].inode.size + length);
	}
	/* TODO: get the block ids of all contents (using sfs_get_file_content() */
	bids = malloc(length/BLOCK_SIZE + 1);
	n = sfs_get_file_content(bids, fd, cur, length);

	/* TODO: main loop, go through every block, copy the necessary parts
	   to the buffer, consult the hint in the document. Do not forget to 
	   flush to the disk.
	*/
	remaining = length;
	offset = cur % BLOCK_SIZE;
	if (BLOCK_SIZE - offset > remaining)
	{
		to_copy = remaining;
	}
	else
	{
		to_copy = BLOCK_SIZE - offset;
	}
	for (i = 0; i < n; i++)
	{
		memcpy(tmp + offset , buf, to_copy);
		
		sfs_write_block((char*)&tmp, bids[i]);
		remaining -= to_copy;
		offset = 0;
		
		if (remaining > BLOCK_SIZE)
		{
			to_copy = BLOCK_SIZE - offset;
		} 
		else 
		{
			to_copy = remaining;
		}
	}
	/* TODO: update the cursor and free the temp buffer
	   for sfs_get_file_content()
	*/
	fdtable[fd].cur += length;
	if (fdtable[fd].inode.size < fdtable[fd].cur)
	{
		fdtable[fd].inode.size = fdtable[fd].cur;
	} 

	sfs_write_block((char*)&(fdtable[fd].inode), fdtable[fd].inode_bid);

	free(bids);

	return length;
}