From d9b03e705292bbe93058f38b6b238e3dd2b7a066 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Sat, 5 Apr 2025 18:16:24 +0200 Subject: [PATCH] fygue: support read() primitive --- CMakeLists.txt | 3 ++ src/fs/fygue/fat/fat.h | 21 ++++++++++++-- src/fs/fygue/fat/fat_file_read.c | 47 ++++++++++++++++++++++++++++++++ src/fs/fygue/fat/fat_file_seek.c | 30 ++++++++++++++++++++ src/fs/fygue/fygue.c | 2 +- src/fs/fygue/fygue.h | 9 +++++- src/fs/fygue/fygue_dir_read.c | 2 +- src/fs/fygue/fygue_file_lseek.c | 11 ++++++++ src/fs/fygue/fygue_file_read.c | 32 ++++++++++++++++++++++ 9 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 src/fs/fygue/fat/fat_file_read.c create mode 100644 src/fs/fygue/fat/fat_file_seek.c create mode 100644 src/fs/fygue/fygue_file_read.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a37596..a80f886 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,6 +271,7 @@ set(SOURCES src/fs/fygue/fygue_file_lseek.c src/fs/fygue/fygue_file_write.c src/fs/fygue/fygue_file_close.c + src/fs/fygue/fygue_file_read.c src/fs/fygue/fat/cluster.c src/fs/fygue/fat/initialize.c src/fs/fygue/fat/fat_dir_read.c @@ -278,6 +279,8 @@ set(SOURCES src/fs/fygue/fat/fat_dir_stat.c src/fs/fygue/fat/fat_file_stat.c src/fs/fygue/fat/fat_file_close.c + src/fs/fygue/fat/fat_file_read.c + src/fs/fygue/fat/fat_file_seek.c src/fs/fygue/fat/resolve.c src/fs/fygue/fat/sector.c src/fs/fygue/flash/cluster.c diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index 83e221c..129ef1b 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -89,6 +89,8 @@ struct fygue_fat_file int cluster_count; } *chunk; int chunk_count; + int chunk_rd_index; + int chunk_rd_offset; }; /* fygue_fat_resolve: internal resolve information */ @@ -145,14 +147,29 @@ extern int fygue_fat_dir_stat( // File interface //--- -/* fygue_fat_file_stat(): directory stat primitive */ +/* fygue_fat_file_read(): read primitive */ +extern int fygue_fat_file_read( + struct fygue_fat *fat, + struct fygue_fat_file *file, + void *buffer, + size_t size +); + +/* fygue_fat_file_stat(): stat primitive */ extern int fygue_fat_file_stat( struct fygue_fat *fat, struct fygue_fat_file *file, struct stat *statbuf ); -/* fygue_fat_file_close(): closedir primitive */ +/* fygue_fat_file_seek(): lseek primitive */ +extern int fygue_fat_file_seek( + struct fygue_fat *fat, + struct fygue_fat_file *file, + off_t offset +); + +/* fygue_fat_file_close(): close primitive */ extern int fygue_fat_file_close( struct fygue_fat *fat, struct fygue_fat_file *dir diff --git a/src/fs/fygue/fat/fat_file_read.c b/src/fs/fygue/fat/fat_file_read.c new file mode 100644 index 0000000..c92eb6e --- /dev/null +++ b/src/fs/fygue/fat/fat_file_read.c @@ -0,0 +1,47 @@ +#include +#include +#include "fat.h" + +/* fygue_fat_file_read(): read primitive */ +int fygue_fat_file_read( + struct fygue_fat *fat, + struct fygue_fat_file *file, + void *buffer, + size_t size +) { + void *chunk_data_addr; + size_t chunk_data_available; + size_t chunk_data_offset; + size_t read; + + if (fat == NULL || file == NULL || buffer == NULL) { + errno = EIO; + return -1; + } + if (file->chunk == NULL) { + errno = EIO; + return -1; + } + read = 0; + chunk_data_offset = file->chunk_rd_offset; + while (read < size) + { + if (file->chunk_rd_index >= file->chunk_count) + break; + chunk_data_addr = (void*)file->chunk[file->chunk_rd_index].addr; + chunk_data_available = file->chunk[file->chunk_rd_index].size; + chunk_data_available -= chunk_data_offset; + if (read + chunk_data_available > size) + { + chunk_data_offset = size - read; + memcpy(buffer, chunk_data_addr, chunk_data_offset); + break; + } + memcpy(buffer, chunk_data_addr, chunk_data_available); + read += chunk_data_available; + file->chunk_rd_index += 1; + chunk_data_offset = 0; + } + file->chunk_rd_offset = chunk_data_offset; + return read; +} diff --git a/src/fs/fygue/fat/fat_file_seek.c b/src/fs/fygue/fat/fat_file_seek.c new file mode 100644 index 0000000..458ad64 --- /dev/null +++ b/src/fs/fygue/fat/fat_file_seek.c @@ -0,0 +1,30 @@ +#include +#include "fat.h" + +/* fygue_fat_file_seek(): seek primitive */ +int fygue_fat_file_seek( + struct fygue_fat *fat, + struct fygue_fat_file *file, + off_t offset +) { + off_t offset_test; + + if (fat == NULL || file == NULL) { + errno = EIO; + return -1; + } + offset_test = 0; + file->chunk_rd_index = 0; + file->chunk_rd_offset = 0; + for (int i = 0; i < file->chunk_count; i++) + { + offset_test += file->chunk[i].size; + if (offset_test > offset) { + file->chunk_rd_offset = offset - offset_test; + return 0; + } + file->chunk_rd_index += 1; + } + errno = EIO; + return -1; +} diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index b532cdf..7bfd5b1 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -84,7 +84,7 @@ int fygue_resolve(char const * const path, struct fygue_resolve *resolve) //--- const fs_descriptor_type_t fygue_descriptor_type = { - .read = NULL, + .read = (void*)&fygue_file_read, .write = (void*)&fygue_file_write, .lseek = (void*)&fygue_file_lseek, .close = (void*)&fygue_file_close, diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h index 1f919a9..6e1d931 100644 --- a/src/fs/fygue/fygue.h +++ b/src/fs/fygue/fygue.h @@ -114,7 +114,7 @@ extern off_t fygue_dir_lseek( ); /* fygue_dir_write(): write directory (EISDIR) */ -ssize_t fygue_dir_write( +extern ssize_t fygue_dir_write( struct fygue_descriptor *desc, void *buffer, size_t size @@ -127,6 +127,13 @@ extern int fygue_dir_close(struct fygue_descriptor *desc); // File interface //--- +/* fygue_file_read(): read primitive */ +extern ssize_t fygue_file_read( + struct fygue_descriptor *desc, + void *buffer, + size_t size +); + /* fygue_file_lseek(): seek directory */ extern off_t fygue_file_lseek( struct fygue_descriptor *desc, diff --git a/src/fs/fygue/fygue_dir_read.c b/src/fs/fygue/fygue_dir_read.c index 626da97..b72148c 100644 --- a/src/fs/fygue/fygue_dir_read.c +++ b/src/fs/fygue/fygue_dir_read.c @@ -24,7 +24,7 @@ static int _fygue_dir_fat_read( rc = fygue_fat_dir_read( &(fsinfo->fat), - &desc->resolve.dir.fat, + &(desc->resolve.dir.fat), &fat_dirent ); if (rc <= -3) diff --git a/src/fs/fygue/fygue_file_lseek.c b/src/fs/fygue/fygue_file_lseek.c index a85cdeb..bd3da94 100644 --- a/src/fs/fygue/fygue_file_lseek.c +++ b/src/fs/fygue/fygue_file_lseek.c @@ -6,6 +6,8 @@ off_t fygue_file_lseek( off_t offset, int whence ) { + struct fygue_fsinfo *fsinfo; + ENOTSUP_IF_NOT_FYGUE(-1); if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { errno = EBADF; @@ -15,6 +17,10 @@ off_t fygue_file_lseek( errno = EINVAL; return -1; } + if (fygue_mount(&fsinfo, true) != 0) { + errno = EIO; + return -1; + } if(whence == SEEK_CUR) offset += desc->resolve.dir.pos; if(whence == SEEK_END) @@ -24,5 +30,10 @@ off_t fygue_file_lseek( return -1; } desc->resolve.file.cursor = offset; + fygue_fat_file_seek( + &(fsinfo->fat), + &(desc->resolve.file.fat), + offset + ); return desc->resolve.file.cursor; } diff --git a/src/fs/fygue/fygue_file_read.c b/src/fs/fygue/fygue_file_read.c new file mode 100644 index 0000000..2a93995 --- /dev/null +++ b/src/fs/fygue/fygue_file_read.c @@ -0,0 +1,32 @@ +#include +#include +#include "fygue.h" + +/* fygue_file_read(): write directory (EISDIR) */ +ssize_t fygue_file_read( + struct fygue_descriptor *desc, + void *buffer, + size_t size +) { + struct fygue_fsinfo *fsinfo; + + ENOTSUP_IF_NOT_FYGUE(-1); + if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { + errno = EBADF; + return -1; + } + if (buffer == NULL) { + errno = EFAULT; + return -1; + } + if (fygue_mount(&fsinfo, true) != 0) { + errno = EIO; + return -1; + } + return fygue_fat_file_read( + &(fsinfo->fat), + &(desc->resolve.file.fat), + buffer, + size + ); +}