From eaa0602225a0fe6a98e067dde99cfd0007be392b Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Sat, 5 Apr 2025 13:34:42 +0200 Subject: [PATCH] fygue: fix FAT cluster resolution + support stat() for directory + support stat(), lseek() and write() (EROFS) for file --- CMakeLists.txt | 2 ++ src/fs/fygue/fat/cluster.c | 47 ++++++++++++++++++++++++++++----- src/fs/fygue/fat/fat.h | 2 -- src/fs/fygue/fat/initialize.c | 13 +++++---- src/fs/fygue/fygue.c | 6 ++--- src/fs/fygue/fygue.h | 26 ++++++++++++++++++ src/fs/fygue/fygue_dir_close.c | 1 + src/fs/fygue/fygue_dir_lseek.c | 5 ++++ src/fs/fygue/fygue_file_lseek.c | 28 ++++++++++++++++++++ src/fs/fygue/fygue_file_write.c | 22 +++++++++++++++ 10 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 src/fs/fygue/fygue_file_lseek.c create mode 100644 src/fs/fygue/fygue_file_write.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a68690..a98f375 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,6 +268,8 @@ set(SOURCES src/fs/fygue/fygue_dir_lseek.c src/fs/fygue/fygue_dir_write.c src/fs/fygue/fygue_dir_close.c + src/fs/fygue/fygue_file_lseek.c + src/fs/fygue/fygue_file_write.c src/fs/fygue/fat/cluster.c src/fs/fygue/fat/initialize.c src/fs/fygue/fat/fat_dir_read.c diff --git a/src/fs/fygue/fat/cluster.c b/src/fs/fygue/fat/cluster.c index c3b26e6..d6d0301 100644 --- a/src/fs/fygue/fat/cluster.c +++ b/src/fs/fygue/fat/cluster.c @@ -2,29 +2,64 @@ ** fygue/fat/cluster - FAT cluster handling */ #include "fat.h" +#include "../flash/flash.h" //--- // Public //--- -/* fygue_fat_cluster_get_next() - find the next cluster ID of a file */ +/* fygue_fat_cluster_get_next() - find the next cluster ID of a file + * + * returns + * -7 next cluster unused (0x0000) + * -6 next cluster end (0xffff) + * -5 internal error + * -4 provided cluster unused (0x0000) + * -3 provided cluster end (0xffff) + * -2 provided invalid cluster (root or "out of fat") + * -1 argument error + * 0 success + * + * todo + * - ensure FAT1 information is the same ? */ int fygue_fat_cluster_get_next(struct fygue_fat *fat, int *cluster_current) { uint16_t *fat0; + int nb_entry_per_sector; + int cluster_sector; + int cluster_real; int cluster; + int rc; if (fat == NULL || cluster_current == NULL) return -1; cluster = *cluster_current; + if (cluster == 0xffff) + return -3; + if (cluster == 0x0000) + return -4; if (cluster <= 1) return -2; if (cluster >= fat->ClusterCount) return -2; - fat0 = (void*)fat->FAT0Addr; - if (fat0[cluster] == 0xffff) - return -3; - *cluster_current = fat0[cluster]; - return 0; + nb_entry_per_sector = fat->SectorSize / 2; + cluster_sector = cluster / nb_entry_per_sector; + cluster_real = cluster - (cluster_sector * nb_entry_per_sector); + rc = fygue_fat_sector_get_addr( + fat, + (void*)&fat0, + fat->FAT0SectorID + cluster_sector + ); + if (rc < 0) + return -5; + rc = 0; + cluster = FAT_WORD(fat0[cluster_real]); + if (cluster == 0xffff) + rc = -6; + if (cluster == 0x0000) + rc = -7; + *cluster_current = cluster; + return rc; } /* fygue_fat_cluster_get_sector() - get sector ID from cluster ID */ diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index 977f99d..c321a1b 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -44,8 +44,6 @@ struct fygue_fat int FAT1SectorID; int RootSectorID; int DataSectorID; - uintptr_t FAT0Addr; - uintptr_t FAT1Addr; uintptr_t RootAddr; uintptr_t BPB; struct { diff --git a/src/fs/fygue/fat/initialize.c b/src/fs/fygue/fat/initialize.c index e16e9ed..e498707 100644 --- a/src/fs/fygue/fat/initialize.c +++ b/src/fs/fygue/fat/initialize.c @@ -147,23 +147,26 @@ static int _fygue_fat_configure(struct fygue_fat *fat) } /* _fygue_fat_prepare() - prepare logic information */ -static int _fygue_fat_prepare(struct fygue_fat *fat) { +static int _fygue_fat_prepare(struct fygue_fat *fat) +{ int rc; - rc = fygue_flash_cmap_lsector_get_addr( - &fat->_flash.cmap, +#if 0 + rc = fygue_fat_sector_get_addr( + fat, &fat->FAT0Addr, fat->FAT0SectorID ); if (rc != 0) return -1; - rc = fygue_flash_cmap_lsector_get_addr( - &fat->_flash.cmap, + rc = fygue_fat_sector_get_addr( + fat, (void*)&fat->FAT1Addr, fat->FAT1SectorID ); if (rc != 0) return -1; +#endif rc = fygue_flash_cmap_lsector_get_addr( &fat->_flash.cmap, &fat->RootAddr, diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index 169de06..2a42d48 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -85,8 +85,8 @@ int fygue_resolve(char const * const path, struct fygue_resolve *resolve) const fs_descriptor_type_t fygue_descriptor_type = { .read = NULL, - .write = NULL, - .lseek = NULL, + .write = (void*)&fygue_file_write, + .lseek = (void*)&fygue_file_lseek, .close = NULL, }; @@ -94,5 +94,5 @@ const fs_descriptor_type_t fygue_dir_descriptor_type = { .read = (void*)&fygue_dir_read, .write = (void*)&fygue_dir_write, .lseek = (void*)&fygue_dir_lseek, - .close = NULL, + .close = (void*)&fygue_dir_close, }; diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h index 8ea0003..cad2fe9 100644 --- a/src/fs/fygue/fygue.h +++ b/src/fs/fygue/fygue.h @@ -65,6 +65,7 @@ struct fygue_resolve { struct { off_t cursor; struct fygue_fat_file fat; + off_t size; } file; struct { struct fygue_fat_dir fat; @@ -94,6 +95,10 @@ extern int fygue_resolve( struct fygue_resolve *resolve ); +//--- +// Directory interface +//--- + /* fygue_dir_read(): directory read implementation */ extern int fygue_dir_read( struct fygue_descriptor *desc, @@ -115,6 +120,27 @@ ssize_t fygue_dir_write( size_t size ); +/* fygue_dir_close(): close directory */ +extern int fygue_dir_close(struct fygue_descriptor *desc); + +//--- +// File interface +//--- + +/* fygue_file_lseek(): seek directory */ +extern off_t fygue_file_lseek( + struct fygue_descriptor *desc, + off_t offset, + int whence +); + +/* fygue_file_write(): write directory (EROFS) */ +extern ssize_t fygue_file_write( + struct fygue_descriptor *desc, + void *buffer, + size_t size +); + #ifdef __cplusplus } #endif diff --git a/src/fs/fygue/fygue_dir_close.c b/src/fs/fygue/fygue_dir_close.c index a09dba9..518607e 100644 --- a/src/fs/fygue/fygue_dir_close.c +++ b/src/fs/fygue/fygue_dir_close.c @@ -3,6 +3,7 @@ #include "fygue.h" #include "fat/fat.h" +/* fygue_dir_close(): close directory */ int fygue_dir_close(struct fygue_descriptor *desc) { struct fygue_fsinfo *fsinfo; diff --git a/src/fs/fygue/fygue_dir_lseek.c b/src/fs/fygue/fygue_dir_lseek.c index 76e1a71..fa3184c 100644 --- a/src/fs/fygue/fygue_dir_lseek.c +++ b/src/fs/fygue/fygue_dir_lseek.c @@ -26,10 +26,15 @@ off_t fygue_dir_lseek( off_t offset, int whence ) { + ENOTSUP_IF_NOT_FYGUE(-1); if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { errno = EBADF; return -1; } + if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) { + errno = EINVAL; + return -1; + } if(whence == SEEK_CUR) offset += desc->resolve.dir.pos; if(whence == SEEK_END) { diff --git a/src/fs/fygue/fygue_file_lseek.c b/src/fs/fygue/fygue_file_lseek.c new file mode 100644 index 0000000..a85cdeb --- /dev/null +++ b/src/fs/fygue/fygue_file_lseek.c @@ -0,0 +1,28 @@ +#include "fygue.h" + +/* fygue_file_lseek(): seek directory */ +off_t fygue_file_lseek( + struct fygue_descriptor *desc, + off_t offset, + int whence +) { + ENOTSUP_IF_NOT_FYGUE(-1); + if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { + errno = EBADF; + return -1; + } + if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) { + errno = EINVAL; + return -1; + } + if(whence == SEEK_CUR) + offset += desc->resolve.dir.pos; + if(whence == SEEK_END) + offset += desc->resolve.file.size; + if(offset < 0 || offset >= desc->resolve.file.size + 1) { + errno = EINVAL; + return -1; + } + desc->resolve.file.cursor = offset; + return desc->resolve.file.cursor; +} diff --git a/src/fs/fygue/fygue_file_write.c b/src/fs/fygue/fygue_file_write.c new file mode 100644 index 0000000..c694d8f --- /dev/null +++ b/src/fs/fygue/fygue_file_write.c @@ -0,0 +1,22 @@ +#include "fygue.h" + +/* fygue_file_write(): write directory (EISDIR) */ +ssize_t fygue_file_write( + struct fygue_descriptor *desc, + void *buffer, + size_t size +) { + 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 (size == 0) + return 0; + errno = EROFS; + return -1; +}