[wip] add read and write
This commit is contained in:
parent
4f610340f5
commit
87f3239c52
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
|
@ -15,8 +17,10 @@
|
||||||
|
|
||||||
#if ENABLE_STDOUT == 1
|
#if ENABLE_STDOUT == 1
|
||||||
#define pr_stdout(...) { printf(__VA_ARGS__); }
|
#define pr_stdout(...) { printf(__VA_ARGS__); }
|
||||||
|
#define write_stdout(data, size) { write(1, (data), (size)); }
|
||||||
#else
|
#else
|
||||||
#define pr_stdout(...) {}
|
#define pr_stdout(...) {}
|
||||||
|
#define write_stdout(data, size) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
306
src/fs.c
306
src/fs.c
|
@ -587,6 +587,312 @@ int fs_open(void *d)
|
||||||
return 0;
|
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 fs_close(void *d)
|
||||||
{
|
{
|
||||||
int fd = *((int *) d);
|
int fd = *((int *) d);
|
||||||
|
|
Loading…
Reference in New Issue