From f4dd03dd800d7cf2d42169b6f30c10585c5a78c4 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 24 May 2021 18:32:58 +0200 Subject: Update filesystem for writing with offset --- src/filesystem.c | 138 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/filesystem.c b/src/filesystem.c index 4a55818..cac2805 100644 --- a/src/filesystem.c +++ b/src/filesystem.c @@ -62,18 +62,20 @@ typedef struct FileSystem { FileIndex files[FILE_INDEX_NUM]; } FileSystem; +#define FILE_BLOCK_CAPACITY (FILE_BLOCK_SIZE - sizeof(FileBlock)) + EWRAM_BSS static FileSystem filesystem; void -_fs_read(u8 *dst, size_t pos, size_t n_bytes) { +_fs_read(u8 *dst, u16 pos, u16 n_bytes) { for (size_t i = 0; i < n_bytes; ++i) { dst[i] = SRAM[pos + i]; } } void -_fs_write(u8 *src, size_t pos, size_t n_bytes) { +_fs_write(u8 *src, u16 pos, u16 n_bytes) { for (size_t i = 0; i < n_bytes; ++i) { SRAM[pos + i] = src[i]; } @@ -96,7 +98,7 @@ fs_init(void) { .prev_block = FS_NULL, }; for (size_t i = 0; i < FILE_INDEX_NUM; ++i) { - size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i; + u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i; _fs_write(&block, block_pos, sizeof(FileBlock)); } @@ -112,12 +114,12 @@ fs_init(void) { } } -void inline +void _fs_update_filesystem_header(void) { _fs_write(&filesystem, 0, offsetof(FileSystem, files)); }; -void inline +void _fs_update_file_index(u16 index) { _fs_write(&filesystem.files[index], offsetof(FileSystem, files) + index * sizeof(FileIndex), @@ -132,7 +134,7 @@ typedef enum { typedef struct File { u8 index; - u16 cur; + u16 offset; OpenMode mode; } File; @@ -152,8 +154,8 @@ fs_open_file(char *name, OpenMode mode) { // Create a new file if there is space. if (filesystem.num_files < FILE_INDEX_NUM) { - size_t index = filesystem.num_files++; - size_t k = 0; + u16 index = filesystem.num_files++; + u16 k = 0; while(*name) { filesystem.files[index].name[k++] = *name++; } @@ -167,6 +169,20 @@ fs_open_file(char *name, OpenMode mode) { return (File){FS_NULL, 0, mode}; } +u16 +fs_file_size(File *file) { + u16 size = 0; + FileBlock block; + u16 blk_id = filesystem.files[file->index].first_block; + while (blk_id != FS_NULL) { + u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; + _fs_read(&block, block_pos, sizeof(FileBlock)); + size += block.size; + blk_id = block.next_block; + } + return size; +} + u8 _fs_init_new_block(void) { // Find free block. @@ -188,18 +204,18 @@ _fs_init_new_block(void) { #include "text.h" -// Recursively free blocks starting at block_id. To improve performance, the +// Recursively free blocks starting at blk_id. To improve performance, the // filesystem header is updated in memory but not written to disk. It is // responsability of the caller to perform the filesystem update. void -_fs_free_blocks(u8 block_id) { - if (block_id == FS_NULL) { +_fs_free_blocks(u8 blk_id) { + if (blk_id == FS_NULL) { return; } // Read block. FileBlock block; - size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; + u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; _fs_read(&block, block_pos, sizeof(FileBlock)); // Update block. @@ -213,34 +229,31 @@ _fs_free_blocks(u8 block_id) { // Update dirty and busy blocks. filesystem.busy_blocks--; - filesystem.used_blocks[block_id / 8] &= ~(1 << (block_id % 8)); + filesystem.used_blocks[blk_id / 8] &= ~(1 << (blk_id % 8)); _fs_free_blocks(next_block); } // Write to block as a new file. void -_fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { +_fs_write_to_block(u8 *src, u16 n_bytes, u16 blk_offset, u8 blk_id, u8 prev_blk) { // Read initial block. FileBlock block; - size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; + u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; _fs_read(&block, block_pos, sizeof(FileBlock)); - u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)); + u16 block_capacity = FILE_BLOCK_CAPACITY - blk_offset; // Write capacity. u16 block_bytes = MIN(block_capacity, n_bytes); - _fs_write(src, block_pos + sizeof(FileBlock), block_bytes); + _fs_write(src, block_pos + sizeof(FileBlock) + blk_offset, block_bytes); if (n_bytes > block_capacity) { if (block.next_block == FS_NULL) { // Find new available block and initialize it. block.next_block = _fs_init_new_block(); } - _fs_write_to_block( - src + block_capacity, - n_bytes - block_capacity, - block.next_block, - block_id); + _fs_write_to_block(src + block_capacity, n_bytes - block_capacity, 0, + block.next_block, blk_id); } else if (block.next_block != FS_NULL){ // Recursively free unused blocks. _fs_free_blocks(block.next_block); @@ -249,18 +262,18 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { } // Update block header. - if (prev_block != FS_NULL) { - block.prev_block = prev_block; + if (prev_blk != FS_NULL) { + block.prev_block = prev_blk; } block.size = block_bytes; _fs_write(&block, block_pos, sizeof(FileBlock)); } // void -// _fs_append_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { +// _fs_append_to_block(u8 *src, u16 n_bytes, u8 blk_id, u8 prev_block) { // // Read initial block. // FileBlock block; -// size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; +// size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; // _fs_read(&block, block_pos, sizeof(FileBlock)); // u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)) - block.size; @@ -270,7 +283,7 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { // // txt_printf("cap: %d\n", block_capacity); // // txt_printf("bytes: %d\n", n_bytes); -// // txt_printf("id: %d\n", block_id); +// // txt_printf("id: %d\n", blk_id); // if (n_bytes > block_capacity) { // if (block.next_block == FS_NULL) { // // Find new available block and initialize it. @@ -282,62 +295,83 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { // src + block_capacity, // n_bytes - block_capacity, // block.next_block, -// block_id); +// blk_id); // } // // Update block header. // if (prev_block != FS_NULL) { -// block.prev_block = prev_block; +// block.prev_block = prev_bloc7f8k; // } // block.size += block_bytes; // _fs_write(&block, block_pos, sizeof(FileBlock)); // } -size_t -fs_write(u8 *src, size_t n_bytes, u16 offset, bool append, File *file) { +u16 +fs_write(u8 *src, u16 n_bytes, File *file) { + if (file->mode != FS_OPEN_WRITE && file->mode != FS_OPEN_APPEND) { + return 0; + } + FileIndex *file_idx = &filesystem.files[file->index]; - // TODO: Account for offset. - // If this is a new file. + u8 blk_id = FS_NULL; + u16 offset = file->offset; if (file_idx->first_block == FS_NULL) { - // Check how many blocks will this write require and if we have enough + // Check how many blocks will this write requires and if we have enough // available. - u16 blocks_required = n_bytes / (FILE_BLOCK_SIZE - sizeof(FileBlock)); + u16 blocks_required = n_bytes / FILE_BLOCK_CAPACITY; u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks; if (blocks_required > blocks_available) { return 0; } // Find the first available block. - u8 block_id = _fs_init_new_block(); - file_idx->first_block = block_id; + blk_id = _fs_init_new_block(); + file_idx->first_block = blk_id; // Update file index on SRAM. _fs_update_file_index(file->index); } else { - // TODO: Check how many blocks will this write require and if we have + // Check how many blocks will this write requires and if we have // enough available. + u16 file_size = fs_file_size(file); + u16 blocks_in_file = file_size / FILE_BLOCK_SIZE; + u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks + blocks_in_file; + u16 blocks_required = (n_bytes + offset) / FILE_BLOCK_CAPACITY; + if (blocks_required > blocks_available) { + return 0; + } + + blk_id = file_idx->first_block; + + // If there is an offset find the block index and relative offset. + if (offset >= FILE_BLOCK_CAPACITY) { + u16 n_blocks_offset = offset / FILE_BLOCK_CAPACITY; + for (size_t i = 0; i < n_blocks_offset; ++i) { + FileBlock block; + u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id; + _fs_read(&block, block_pos, sizeof(FileBlock)); + blk_id = block.next_block; + if (blk_id == FS_NULL) { + return 0; + } + } + offset = offset % FILE_BLOCK_CAPACITY; + } } - // txt_printf("id: %d", file_idx->first_block); // Write to block. - _fs_write_to_block(src, n_bytes, file_idx->first_block, FS_NULL); - - // // Update file index. - // if (append) { - // if (offset + n_bytes > file->size) { - // file->size = offset + n_bytes; - // } - // } else { - // file->size = offset + n_bytes; - // } - // _fs_write(file, FILE_INDEX_OFFSET + file_index * sizeof(File), sizeof(File)); + if (file->mode == FS_OPEN_WRITE) { + _fs_write_to_block(src, n_bytes, offset, blk_id, FS_NULL); + } else { + // TODO: Append... + } return n_bytes; } -size_t -fs_read(u8 *dst, size_t n_bytes, u16 offset, File *file) { +u16 +fs_read(u8 *dst, u16 n_bytes, u16 offset, File *file) { // File *file = &filesystem.files[file_index]; // // Check if the offset is within limits. -- cgit v1.2.1