[wip] add read and write
This commit is contained in:
		
							parent
							
								
									4f610340f5
								
							
						
					
					
						commit
						87f3239c52
					
				@ -3,6 +3,8 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "color.h"
 | 
			
		||||
 | 
			
		||||
@ -15,8 +17,10 @@
 | 
			
		||||
 | 
			
		||||
#if ENABLE_STDOUT == 1
 | 
			
		||||
	#define pr_stdout(...) { printf(__VA_ARGS__); }
 | 
			
		||||
	#define write_stdout(data, size) { write(1, (data), (size)); }
 | 
			
		||||
#else
 | 
			
		||||
	#define pr_stdout(...) {}
 | 
			
		||||
	#define write_stdout(data, size) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										306
									
								
								src/fs.c
									
									
									
									
									
								
							
							
						
						
									
										306
									
								
								src/fs.c
									
									
									
									
									
								
							@ -587,6 +587,312 @@ int fs_open(void *d)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_seek(void *d)
 | 
			
		||||
{
 | 
			
		||||
	int fd = ((int *) d)[0];
 | 
			
		||||
	int offset = ((int *) d)[1];
 | 
			
		||||
 | 
			
		||||
	if (!fs_file_descriptions[fd].inode) {
 | 
			
		||||
		pr_err("fd %d is not open\n", fd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct fs_inode f;
 | 
			
		||||
	read_block(fs_file_descriptions[fd].inode, (void *) &f);
 | 
			
		||||
 | 
			
		||||
	if (offset > f.size) {
 | 
			
		||||
		pr_err("offset is larger than file (%d > %d)\n", offset, f.size);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pr("Moving rw_offset of fd %d: %d -> %d\n",
 | 
			
		||||
			fd, fs_file_descriptions[fd].rw_offset, offset);
 | 
			
		||||
	fs_file_descriptions[fd].rw_offset = offset;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void read_fd_block(unsigned int fd, unsigned int block_index, unsigned char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct fs_inode f;
 | 
			
		||||
	read_block(fs_file_descriptions[fd].inode, (void *) &f);
 | 
			
		||||
 | 
			
		||||
	if (block_index < BLOCK_ADDRESSES_PER_INODE) {
 | 
			
		||||
		if (f.blocks[block_index])
 | 
			
		||||
			read_block(f.blocks[block_index], (void *) buf);
 | 
			
		||||
		else
 | 
			
		||||
			memset(buf, 0, FS_BLOCK_SIZE);
 | 
			
		||||
	} else {
 | 
			
		||||
		int ext_no = (block_index - BLOCK_ADDRESSES_PER_INODE) / BLOCK_ADDRESSES_PER_INODE_EXTENSION;
 | 
			
		||||
		int ext_offset = (block_index - BLOCK_ADDRESSES_PER_INODE) % BLOCK_ADDRESSES_PER_INODE_EXTENSION;
 | 
			
		||||
 | 
			
		||||
		unsigned int target_extension_address;
 | 
			
		||||
		unsigned int i;
 | 
			
		||||
 | 
			
		||||
		// seek to target extension address
 | 
			
		||||
		for (
 | 
			
		||||
			target_extension_address = f.next_extension, i = 0;
 | 
			
		||||
			(i < ext_no) && target_extension_address;
 | 
			
		||||
			i++
 | 
			
		||||
		) {
 | 
			
		||||
			struct fs_inode_extension ext;
 | 
			
		||||
			read_block(target_extension_address, (void *) &ext);
 | 
			
		||||
			target_extension_address = ext.next_extension;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!target_extension_address) {
 | 
			
		||||
			memset(buf, 0, FS_BLOCK_SIZE);
 | 
			
		||||
		} else {
 | 
			
		||||
			struct fs_inode_extension ext;
 | 
			
		||||
			read_block(target_extension_address, (void *) &ext);
 | 
			
		||||
 | 
			
		||||
			if (!ext.blocks[ext_offset])
 | 
			
		||||
				memset(buf, 0, FS_BLOCK_SIZE);
 | 
			
		||||
			else
 | 
			
		||||
				read_block(ext.blocks[ext_offset], (void *) buf);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int write_fd_block(unsigned int fd, unsigned int block_index, unsigned char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct fs_inode f;
 | 
			
		||||
	read_block(fs_file_descriptions[fd].inode, (void *) &f);
 | 
			
		||||
 | 
			
		||||
	if (block_index < BLOCK_ADDRESSES_PER_INODE) {
 | 
			
		||||
		if (!f.blocks[block_index]) {
 | 
			
		||||
			int new_block = find_free_block();
 | 
			
		||||
			if (!new_block) {
 | 
			
		||||
				pr_err("failed to write to fd=%d block=%d: can't allocate block for writing file data\n",
 | 
			
		||||
						fd, block_index);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			mark_used(new_block);
 | 
			
		||||
 | 
			
		||||
			f.blocks[block_index] = new_block;
 | 
			
		||||
			write_block(fs_file_descriptions[fd].inode, (void *) &f);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		write_block(f.blocks[block_index], (void *) buf);
 | 
			
		||||
	} else {
 | 
			
		||||
		int ext_no = (block_index - BLOCK_ADDRESSES_PER_INODE) / BLOCK_ADDRESSES_PER_INODE_EXTENSION;
 | 
			
		||||
		int ext_offset = (block_index - BLOCK_ADDRESSES_PER_INODE) % BLOCK_ADDRESSES_PER_INODE_EXTENSION;
 | 
			
		||||
 | 
			
		||||
		// treat switch from base inode to inode extension as special case
 | 
			
		||||
		if (!f.next_extension) {
 | 
			
		||||
			int new_block = find_free_block();
 | 
			
		||||
			if (!new_block) {
 | 
			
		||||
				pr_err("failed to write to fd=%d block=%d: can't allocate block for inode extension\n",
 | 
			
		||||
						fd, block_index);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			mark_used(new_block);
 | 
			
		||||
 | 
			
		||||
			struct fs_inode_extension ext;
 | 
			
		||||
			memset(&ext, 0, sizeof(struct fs_inode_extension));
 | 
			
		||||
 | 
			
		||||
			f.next_extension = new_block;
 | 
			
		||||
			write_block(fs_file_descriptions[fd].inode, (void *) &f);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		unsigned int target_extension_address;
 | 
			
		||||
		unsigned int previous_extension_address = f.next_extension;
 | 
			
		||||
		unsigned int i;
 | 
			
		||||
 | 
			
		||||
		// seek to target extension address
 | 
			
		||||
		for (
 | 
			
		||||
			target_extension_address = previous_extension_address, i = 0;
 | 
			
		||||
			(i < ext_no);
 | 
			
		||||
			i++
 | 
			
		||||
		) {
 | 
			
		||||
			if (!target_extension_address) {
 | 
			
		||||
				int new_block = find_free_block();
 | 
			
		||||
				if (!new_block) {
 | 
			
		||||
					pr_err("failed to write to fd=%d block=%d: can't allocate block for inode extension\n",
 | 
			
		||||
							fd, block_index);
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
				mark_used(new_block);
 | 
			
		||||
 | 
			
		||||
				// updating previous inode extension
 | 
			
		||||
				struct fs_inode_extension prev_ext;
 | 
			
		||||
				read_block(previous_extension_address, (void *) &prev_ext);  // read
 | 
			
		||||
				prev_ext.next_extension = new_block;                         // modify
 | 
			
		||||
				write_block(previous_extension_address, (void *) &prev_ext); // write
 | 
			
		||||
 | 
			
		||||
				// writing new inode extension
 | 
			
		||||
				struct fs_inode_extension ext;
 | 
			
		||||
				memset(&ext, 0, sizeof(struct fs_inode_extension));
 | 
			
		||||
				write_block(target_extension_address, (void *) &ext);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			struct fs_inode_extension ext;
 | 
			
		||||
			read_block(target_extension_address, (void *) &ext);
 | 
			
		||||
			previous_extension_address = target_extension_address;
 | 
			
		||||
			target_extension_address = ext.next_extension;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!target_extension_address) {
 | 
			
		||||
			int new_block = find_free_block();
 | 
			
		||||
			if (!new_block) {
 | 
			
		||||
				pr_err("failed to write to fd=%d block=%d: can't allocate block for inode extension\n",
 | 
			
		||||
						fd, block_index);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			struct fs_inode_extension prev_ext;
 | 
			
		||||
			read_block(previous_extension_address, (void *) &prev_ext);  // read
 | 
			
		||||
			prev_ext.next_extension = new_block;                         // modify
 | 
			
		||||
			write_block(previous_extension_address, (void *) &prev_ext); // write
 | 
			
		||||
 | 
			
		||||
			int new_data_block = find_free_block();
 | 
			
		||||
			if (!new_data_block) {
 | 
			
		||||
				pr_err("failed to write to fd=%d block=%d: can't allocate block for data\n",
 | 
			
		||||
						fd, block_index);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			mark_used(new_block);
 | 
			
		||||
			mark_used(new_data_block);
 | 
			
		||||
 | 
			
		||||
			// writing new inode extension
 | 
			
		||||
			struct fs_inode_extension ext;
 | 
			
		||||
			memset(&ext, 0, sizeof(struct fs_inode_extension));
 | 
			
		||||
			ext.blocks[ext_offset] = new_data_block;
 | 
			
		||||
			write_block(target_extension_address, (void *) &ext);
 | 
			
		||||
 | 
			
		||||
			// writing new data block
 | 
			
		||||
			write_block(new_data_block, (void *) buf);
 | 
			
		||||
		} else {
 | 
			
		||||
			struct fs_inode_extension ext;
 | 
			
		||||
			read_block(target_extension_address, (void *) &ext);
 | 
			
		||||
 | 
			
		||||
			if (!ext.blocks[ext_offset]) {
 | 
			
		||||
				int new_data_block = find_free_block();
 | 
			
		||||
				if (!new_data_block) {
 | 
			
		||||
					pr_err("failed to write to fd=%d block=%d: can't allocate block for data\n",
 | 
			
		||||
							fd, block_index);
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
				mark_used(new_data_block);
 | 
			
		||||
 | 
			
		||||
				ext.blocks[ext_offset] = new_data_block;
 | 
			
		||||
				write_block(target_extension_address, (void *) &ext);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			write_block(ext.blocks[ext_offset], (void *) buf);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_read(void *d)
 | 
			
		||||
{
 | 
			
		||||
	int fd = ((int *) d)[0];
 | 
			
		||||
	int amount = ((int *) d)[1];
 | 
			
		||||
 | 
			
		||||
	if (!fs_file_descriptions[fd].inode) {
 | 
			
		||||
		pr_err("fd %d is not open\n", fd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (amount <= 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	struct fs_inode f;
 | 
			
		||||
	read_block(fs_file_descriptions[fd].inode, (void *) &f);
 | 
			
		||||
 | 
			
		||||
	if (fs_file_descriptions[fd].rw_offset + amount > f.size) {
 | 
			
		||||
		pr_err("can not read outside of a file (offset %d + amount %d > f.size %d)\n",
 | 
			
		||||
				fs_file_descriptions[fd].rw_offset, amount, f.size);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pr("Reading %d bytes from fd %d (offset %d)\n",
 | 
			
		||||
			amount, fd, fs_file_descriptions[fd].rw_offset);
 | 
			
		||||
 | 
			
		||||
	unsigned char *read_data = malloc(amount);
 | 
			
		||||
	unsigned int total_read_data_amount = 0;
 | 
			
		||||
 | 
			
		||||
	// read from first block
 | 
			
		||||
	unsigned char block_buffer[FS_BLOCK_SIZE];
 | 
			
		||||
 | 
			
		||||
	int block_index = fs_file_descriptions[fd].rw_offset / FS_BLOCK_SIZE;
 | 
			
		||||
	int block_offset = fs_file_descriptions[fd].rw_offset % FS_BLOCK_SIZE;
 | 
			
		||||
 | 
			
		||||
	read_fd_block(fd, block_index, block_buffer);
 | 
			
		||||
 | 
			
		||||
	if (block_offset + amount <= FS_BLOCK_SIZE) {
 | 
			
		||||
		memcpy(read_data, &(block_buffer[block_offset]), amount);
 | 
			
		||||
		goto print_read_data;
 | 
			
		||||
	} else {
 | 
			
		||||
		memcpy(read_data, &(block_buffer[block_offset]), FS_BLOCK_SIZE - block_offset);
 | 
			
		||||
		total_read_data_amount += FS_BLOCK_SIZE - block_offset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// read from all next blocks
 | 
			
		||||
	while (amount - total_read_data_amount > 0) {
 | 
			
		||||
		block_index++;
 | 
			
		||||
		read_fd_block(fd, block_index, block_buffer);
 | 
			
		||||
		int bytes_to_read = (amount - total_read_data_amount > FS_BLOCK_SIZE)
 | 
			
		||||
			? FS_BLOCK_SIZE : amount - total_read_data_amount;
 | 
			
		||||
 | 
			
		||||
		memcpy(&(read_data[total_read_data_amount]), block_buffer, bytes_to_read);
 | 
			
		||||
		total_read_data_amount += bytes_to_read;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
print_read_data:
 | 
			
		||||
	pr("Updating fd %d offset: %d -> %d\n",
 | 
			
		||||
			fd, fs_file_descriptions[fd].rw_offset, fs_file_descriptions[fd].rw_offset+amount);
 | 
			
		||||
	fs_file_descriptions[fd].rw_offset += amount;
 | 
			
		||||
 | 
			
		||||
	write_stdout(read_data, amount);
 | 
			
		||||
	pr_stdout("\n");
 | 
			
		||||
 | 
			
		||||
	free(read_data);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_write(void *d)
 | 
			
		||||
{
 | 
			
		||||
	int fd = ((int *) d)[0];
 | 
			
		||||
	char *str = *((char **) d+4);
 | 
			
		||||
	int str_len = strlen(str);
 | 
			
		||||
 | 
			
		||||
	if (!fs_file_descriptions[fd].inode) {
 | 
			
		||||
		pr_err("fd %d is not open\n", fd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (str_len == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	int block_index = fs_file_descriptions[fd].rw_offset / FS_BLOCK_SIZE;
 | 
			
		||||
	int block_offset = fs_file_descriptions[fd].rw_offset % FS_BLOCK_SIZE;
 | 
			
		||||
 | 
			
		||||
	unsigned char data_buffer[FS_BLOCK_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (block_offset + str_len <= FS_BLOCK_SIZE) {
 | 
			
		||||
		read_fd_block(fd, block_index, data_buffer);
 | 
			
		||||
		memcpy(&(data_buffer[block_offset]), str, str_len);
 | 
			
		||||
		write_fd_block(fd, block_index, data_buffer);
 | 
			
		||||
	} else {
 | 
			
		||||
		read_fd_block(fd, block_index, data_buffer);
 | 
			
		||||
		memcpy(&(data_buffer[block_offset]), str, FS_BLOCK_SIZE - block_offset);
 | 
			
		||||
		write_fd_block(fd, block_index, data_buffer);
 | 
			
		||||
 | 
			
		||||
		read_fd_block(fd, block_index+1, data_buffer);
 | 
			
		||||
		memcpy(data_buffer, &(str[FS_BLOCK_SIZE - block_offset]), str_len - block_offset);
 | 
			
		||||
		write_fd_block(fd, block_index+1, data_buffer);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pr("Moving fd %d offset: %d -> %d\n",
 | 
			
		||||
			fd, fs_file_descriptions[fd].rw_offset, fs_file_descriptions[fd].rw_offset + str_len);
 | 
			
		||||
	fs_file_descriptions[fd].rw_offset += str_len;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_close(void *d)
 | 
			
		||||
{
 | 
			
		||||
	int fd = *((int *) d);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user