[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…
Reference in New Issue