From ec6f7cedc540b858417be3979a27a4f1f854f97c Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Thu, 10 Apr 2025 23:40:59 +0200 Subject: [PATCH] fygue: fix read() + fix broken sync() + fix path handling + fix file stat() + various other fixes --- CMakeLists.txt | 1 + src/fs/fs.c | 1 + src/fs/fugue/fugue.c | 12 ++--- src/fs/fygue/fat/fat_dir_read.c | 6 +-- src/fs/fygue/fat/fat_file_read.c | 20 ++++---- src/fs/fygue/fat/fat_file_stat.c | 4 +- src/fs/fygue/fat/fat_open.c | 2 - src/fs/fygue/fat/flash/cluster.c | 3 -- src/fs/fygue/fat/flash/cmap.c | 78 ++++++++++++++++++-------------- src/fs/fygue/fygue.c | 2 +- src/fs/fygue/fygue.h | 5 +- src/fs/fygue/fygue_dir_close.c | 2 - src/fs/fygue/fygue_dir_open.c | 7 +-- src/fs/fygue/fygue_file_close.c | 6 ++- src/fs/fygue/fygue_file_open.c | 1 + src/fs/fygue/fygue_file_read.c | 17 ++++--- src/fs/fygue/fygue_open.c | 2 +- src/fs/fygue/fygue_sync.c | 15 ++++++ src/fs/fygue/fygue_syncfs.c | 5 +- src/kernel/world.c | 2 +- 20 files changed, 108 insertions(+), 83 deletions(-) create mode 100644 src/fs/fygue/fygue_sync.c diff --git a/CMakeLists.txt b/CMakeLists.txt index bb6185d..854fe91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,7 @@ set(SOURCES src/fs/fygue/fygue.c src/fs/fygue/fygue_open.c src/fs/fygue/fygue_syncfs.c + src/fs/fygue/fygue_sync.c src/fs/fygue/fygue_stat.c src/fs/fygue/fygue_mount.c src/fs/fygue/fygue_dir_open.c diff --git a/src/fs/fs.c b/src/fs/fs.c index d6b4a78..30a46e3 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -66,6 +66,7 @@ bool fs_descriptor_is_fygue(fs_descriptor_t const *desc) void fs_fygue_sync(void) { + fygue_sync(); for (int i = 3 ; i < FS_FD_MAX ; i++) { if (fdtable[i].type == NULL) continue; diff --git a/src/fs/fugue/fugue.c b/src/fs/fugue/fugue.c index 7b18137..5ba722b 100644 --- a/src/fs/fugue/fugue.c +++ b/src/fs/fugue/fugue.c @@ -100,15 +100,13 @@ ssize_t fugue_write(void *data0, const void *buf, size_t size) else { gint_world_enter(GINT_WORLD_OS); int rc = BFile_Write(fugue_fd, buf, size); + gint_world_leave(); if(rc < 0) { errno = bfile_error_to_errno(rc); - rc = -1; - } else { - data->pos += rc; - rc = 0; - } - gint_world_leave(); - return rc; + return -1; + } + data->pos += rc; + return rc; } } diff --git a/src/fs/fygue/fat/fat_dir_read.c b/src/fs/fygue/fat/fat_dir_read.c index fdd661c..5008f14 100644 --- a/src/fs/fygue/fat/fat_dir_read.c +++ b/src/fs/fygue/fat/fat_dir_read.c @@ -374,10 +374,10 @@ static int _fygue_readdir_fat_check(struct _fat_info *finfo) /* fygue_fat_dir_read() - readdir-like primitive * * return - * -3 no dirent remaning * -2 internal error * -1 argument error - * 0 success */ + * 0 success + * 1 no directory found */ int fygue_fat_dir_read( struct fygue_fat *fat, struct fygue_fat_dir *dir, @@ -415,5 +415,5 @@ int fygue_fat_dir_read( return 0; } dir->end_of_dirent = true; - return -3; + return 1; } diff --git a/src/fs/fygue/fat/fat_file_read.c b/src/fs/fygue/fat/fat_file_read.c index c92eb6e..034714f 100644 --- a/src/fs/fygue/fat/fat_file_read.c +++ b/src/fs/fygue/fat/fat_file_read.c @@ -9,35 +9,33 @@ int fygue_fat_file_read( void *buffer, size_t size ) { - void *chunk_data_addr; + uintptr_t 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; + if (fat == NULL || file == NULL || buffer == NULL) return -1; - } - if (file->chunk == NULL) { - errno = EIO; + if (file->chunk == NULL) 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_addr = file->chunk[file->chunk_rd_index].addr; + chunk_data_addr += chunk_data_offset; 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); + chunk_data_offset += size - read; + memcpy(buffer, (void*)chunk_data_addr, size - read); + read += size - read; break; } - memcpy(buffer, chunk_data_addr, chunk_data_available); + memcpy(buffer, (void*)chunk_data_addr, chunk_data_available); read += chunk_data_available; file->chunk_rd_index += 1; chunk_data_offset = 0; diff --git a/src/fs/fygue/fat/fat_file_stat.c b/src/fs/fygue/fat/fat_file_stat.c index 21cb6bf..a3b00e9 100644 --- a/src/fs/fygue/fat/fat_file_stat.c +++ b/src/fs/fygue/fat/fat_file_stat.c @@ -9,8 +9,8 @@ static mode_t _get_mode(int attribute) { if (attribute & FYGUE_FAT_ATTR_READ_ONLY) - return S_IFDIR | 0444; - return S_IFDIR | 0777; + return S_IFREG | 0444; + return S_IFREG | 0777; } /* _get_block_size(): return one cluster size */ diff --git a/src/fs/fygue/fat/fat_open.c b/src/fs/fygue/fat/fat_open.c index 9ab2d16..92b7784 100644 --- a/src/fs/fygue/fat/fat_open.c +++ b/src/fs/fygue/fat/fat_open.c @@ -86,8 +86,6 @@ int fygue_fat_open( if (fat == NULL || path == NULL || desc == NULL) return -1; - if (path[0] != '/') - return -1; prefix = path; is_root = true; while (true) diff --git a/src/fs/fygue/fat/flash/cluster.c b/src/fs/fygue/fat/flash/cluster.c index 595cbba..05b2c65 100644 --- a/src/fs/fygue/fat/flash/cluster.c +++ b/src/fs/fygue/fat/flash/cluster.c @@ -25,8 +25,6 @@ struct _bfile_cluster_metadata uint8_t ecc_bitmask_position[3]; } GPACKED(1); -uintptr_t debug_meta = 0; - /* _fygue_flash_cluster_convert - ensure that the provided meta is valid * * notes @@ -179,7 +177,6 @@ static int _fygue_flash_cluster_details( data = (geometry->phy_start | 0xa0000000) + (fsector_id * 0x20000); meta = data + 0x1f000; } - debug_meta = meta; if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0) return -1; if (fcluster->version != 0xffffffff) diff --git a/src/fs/fygue/fat/flash/cmap.c b/src/fs/fygue/fat/flash/cmap.c index e61f0ca..6b1d263 100644 --- a/src/fs/fygue/fat/flash/cmap.c +++ b/src/fs/fygue/fat/flash/cmap.c @@ -33,6 +33,7 @@ static int fygue_flash_cmap_update( struct fygue_flash_cluster *fcluster ) { struct fygue_flash_cmap_entry *entry; + int i; if (cmap == NULL || fcluster == NULL) return -1; @@ -48,14 +49,13 @@ static int fygue_flash_cmap_update( return 1; } } else { - cmap->lcluster = realloc( + cmap->lcluster = reallocarray( cmap->lcluster, - (fcluster->lcluster_id + 1) * sizeof( - struct fygue_flash_cmap_entry - ) + (fcluster->lcluster_id + 1), + sizeof(struct fygue_flash_cmap_entry) ); for ( - int i = cmap->lcluster_id_max ; + i = cmap->lcluster_id_max ; i < fcluster->lcluster_id ; i++ ) { @@ -74,6 +74,42 @@ static int fygue_flash_cmap_update( return 0; } +/* _fygue_flash_cmap_discover(): discover flash information */ +static int _fygue_flash_cmap_discover( + struct fygue_flash *flash, + struct fygue_flash_cmap *cmap +) { + struct fygue_flash_cluster fcluster; + int fsector_id; + int fsector; + int rc; + int j; + + fsector_id = 0; + for ( + fsector = 0 ; + fsector < flash->geometry.fsector_count ; + fsector++ + ) { + if (fsector != 0) + fsector_id += flash->geometry.fcluster_per_fsector; + if (fygue_flash_cluster_get(flash, &fcluster, fsector_id) != 0) + continue; + if (fcluster.kind != 0x22) + continue; + for (j = 1 ; j < (flash->geometry.fcluster_per_fsector - 1) ; j++) + { + rc = fygue_flash_cluster_get(flash, &fcluster, fsector_id + j); + if (rc != 0) + continue; + if (fcluster.kind != 0x11) + continue; + fygue_flash_cmap_update(cmap, &fcluster); + } + } + return 0; +} + //--- // Public //--- @@ -126,37 +162,11 @@ int fygue_flash_cmap_initialize( struct fygue_flash *flash, struct fygue_flash_cmap *cmap ) { - struct fygue_flash_cluster fcluster; - int fsector_id; - int fsector; - int rc; - int j; - if (flash == NULL || cmap == NULL) return -1; - fsector_id = 0; memset(cmap, 0x00, sizeof(struct fygue_flash_cmap)); - for ( - fsector = 0 ; - fsector < flash->geometry.fsector_count ; - fsector++ - ) { - if (fsector != 0) - fsector_id += flash->geometry.fcluster_per_fsector; - if (fygue_flash_cluster_get(flash, &fcluster, fsector_id) != 0) - continue; - if (fcluster.kind != 0x22) - continue; - for (j = 1 ; j < (flash->geometry.fcluster_per_fsector - 1) ; j++) - { - rc = fygue_flash_cluster_get(flash, &fcluster, fsector_id + j); - if (rc != 0) - continue; - if (fcluster.kind != 0x11) - continue; - fygue_flash_cmap_update(cmap, &fcluster); - } - } + if (_fygue_flash_cmap_discover(flash, cmap) != 0) + return -1; if (cmap->lcluster == NULL) return -2; if (cmap->lcluster[0].fcluster_id == 0xffff) @@ -173,7 +183,7 @@ int fygue_flash_cmap_sync( return -1; for (int i = 0 ; i < cmap->lcluster_id_max ; i++) cmap->lcluster[i].version = 0xffffffff; - if (fygue_flash_cmap_initialize(flash, cmap) != 0) + if (_fygue_flash_cmap_discover(flash, cmap) != 0) return -2; return 0; } diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index d13366f..d277574 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -28,7 +28,7 @@ static int _fygue_gfdi_ensure_valid( FYGUE_RET_ERRNO(ENOTSUP); if (fsinfo == NULL) FYGUE_RET_ERRNO(EIO); - if (desc == NULL || desc->type == type) + if (desc == NULL || desc->type != type) FYGUE_RET_ERRNO(EBADF); if (fygue_mount(fsinfo) != 0) FYGUE_RET_ERRNO(EIO); diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h index f2e89e6..9ca8417 100644 --- a/src/fs/fygue/fygue.h +++ b/src/fs/fygue/fygue.h @@ -44,7 +44,10 @@ extern int fygue_open(char const *path, int flags, mode_t mode); /* fygue_stat() - get file or directory information */ extern int fygue_stat(char const *path, struct stat *statbuf); -/* fygue_syncfs() - request filesystem re-synchronisation */ +/* fygue_sync() - request filesystem re-synchronisation */ +extern int fygue_sync(void); + +/* fygue_syncfs() - request filesystem and file re-synchronisation */ extern int fygue_syncfs(void *data); /* fygue_mount() - mount the filesystem */ diff --git a/src/fs/fygue/fygue_dir_close.c b/src/fs/fygue/fygue_dir_close.c index ae5cdc0..a1c1cec 100644 --- a/src/fs/fygue/fygue_dir_close.c +++ b/src/fs/fygue/fygue_dir_close.c @@ -9,8 +9,6 @@ int fygue_dir_close( struct fygue_fsinfo *fsinfo, struct fygue_dir *dir ) { - if(gint[HWFS] != HWFS_FUGUE) - FYGUE_RET_ERRNO(ENOTSUP); if (fsinfo == NULL || dir == NULL) FYGUE_RET_ERRNO(EIO); fygue_fat_dir_close(&(fsinfo->fat), &(dir->fat)); diff --git a/src/fs/fygue/fygue_dir_open.c b/src/fs/fygue/fygue_dir_open.c index cb222ee..e7c88c7 100644 --- a/src/fs/fygue/fygue_dir_open.c +++ b/src/fs/fygue/fygue_dir_open.c @@ -66,7 +66,7 @@ static int _fygue_dir_open_discover( while (true) { rc = fygue_fat_dir_read(&(fsinfo->fat), &(dir->fat), &dirent); - if (rc == -1) + if (rc > 0) return 0; if (rc < 0) break; @@ -74,7 +74,7 @@ static int _fygue_dir_open_discover( if (_fygue_dir_open_table_realloc(dir) != 0) break; } - rc = _fygue_dir_open_convert(&(dir->dirent[dir->pos]), &dirent); + rc = _fygue_dir_open_convert(&(dir->dirent[dir->count]), &dirent); if (rc != 0) break; dir->count += 1; @@ -87,6 +87,7 @@ static int _fygue_dir_open_discover( // Public //--- + /* fygue_dir_open(): directory-specific open */ int fygue_dir_open( struct fygue_fsinfo *fsinfo, @@ -95,7 +96,7 @@ int fygue_dir_open( struct fygue_fat_dir *fat_dir ) { if (fsinfo == NULL || dir == NULL || path == NULL || fat_dir == NULL) - return 1; + return -1; memset(dir, 0x00, sizeof(struct fygue_dir)); dir->path = strdup(path); diff --git a/src/fs/fygue/fygue_file_close.c b/src/fs/fygue/fygue_file_close.c index 936a482..a8057ee 100644 --- a/src/fs/fygue/fygue_file_close.c +++ b/src/fs/fygue/fygue_file_close.c @@ -1,6 +1,6 @@ #include +#include #include "fygue.h" -#include "fat/fat.h" /* fygue_file_close(): close directory */ int fygue_file_close( @@ -10,6 +10,8 @@ int fygue_file_close( if (fsinfo == NULL || file == NULL) FYGUE_RET_ERRNO(EIO); fygue_fat_file_close(&(fsinfo->fat), &(file->fat)); - free(file); + if (file->path != NULL) + free(file->path); + memset(file, 0x00, sizeof(struct fygue_file)); return 0; } diff --git a/src/fs/fygue/fygue_file_open.c b/src/fs/fygue/fygue_file_open.c index 5f9d59e..5160937 100644 --- a/src/fs/fygue/fygue_file_open.c +++ b/src/fs/fygue/fygue_file_open.c @@ -16,6 +16,7 @@ int fygue_file_open( if (file->path == NULL) FYGUE_RET_ERRNO(ENOMEM); file->cursor = 0; + file->size = fat_file->size; memcpy(&(file->fat), fat_file, sizeof(struct fygue_fat_file)); return 0; } diff --git a/src/fs/fygue/fygue_file_read.c b/src/fs/fygue/fygue_file_read.c index 8f6b38c..5cc8e72 100644 --- a/src/fs/fygue/fygue_file_read.c +++ b/src/fs/fygue/fygue_file_read.c @@ -7,14 +7,19 @@ ssize_t fygue_file_read( void *buffer, size_t size ) { + ssize_t read; + if (fsinfo == NULL || file == NULL) FYGUE_RET_ERRNO(EIO); if (buffer == NULL) FYGUE_RET_ERRNO(EFAULT); - return fygue_fat_file_read( - &(fsinfo->fat), - &(file->fat), - buffer, - size - ); + if (file->cursor > 0 && (unsigned)file->cursor >= file->size) + return 0; + if (file->cursor + size >= file->size) + size = file->size - file->cursor; + read = fygue_fat_file_read(&(fsinfo->fat), &(file->fat), buffer, size); + if (read < 0) + FYGUE_RET_ERRNO(EIO); + file->cursor += read; + return read; } diff --git a/src/fs/fygue/fygue_open.c b/src/fs/fygue/fygue_open.c index dfc90fb..68d79e2 100644 --- a/src/fs/fygue/fygue_open.c +++ b/src/fs/fygue/fygue_open.c @@ -23,7 +23,7 @@ int fygue_open_resolve( struct fygue_fat_descriptor fat_desc; struct fygue_fsinfo *fsinfo; - if (path == NULL || path[0] != '/' || desc == NULL) + if (path == NULL || desc == NULL) return -1; if (fygue_mount(&fsinfo) != 0) return -2; diff --git a/src/fs/fygue/fygue_sync.c b/src/fs/fygue/fygue_sync.c new file mode 100644 index 0000000..5eae197 --- /dev/null +++ b/src/fs/fygue/fygue_sync.c @@ -0,0 +1,15 @@ +#include +#include "fygue.h" + +/* fygue_sync() - request filesystem re-synchronisation */ +int fygue_sync(void) +{ + struct fygue_fsinfo *fsinfo; + + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); + if (fygue_mount(&fsinfo) != 0) + FYGUE_RET_ERRNO(EIO); + fsinfo->dirty = true; + return 0; +} diff --git a/src/fs/fygue/fygue_syncfs.c b/src/fs/fygue/fygue_syncfs.c index d741925..b0744f7 100644 --- a/src/fs/fygue/fygue_syncfs.c +++ b/src/fs/fygue/fygue_syncfs.c @@ -4,17 +4,14 @@ /* fygue_syncfs() - request filesystem re-synchronisation */ int fygue_syncfs(void *data) { - struct fygue_fsinfo *fsinfo; struct fygue_descriptor *desc; if(gint[HWFS] != HWFS_FUGUE) FYGUE_RET_ERRNO(ENOTSUP); if (data == NULL) FYGUE_RET_ERRNO(EBADF); - if (fygue_mount(&fsinfo) != 0) - FYGUE_RET_ERRNO(EIO); desc = data; desc->dirty = true; - fsinfo->dirty = true; + fygue_sync(); return 0; } diff --git a/src/kernel/world.c b/src/kernel/world.c index a984768..ed610b2 100644 --- a/src/kernel/world.c +++ b/src/kernel/world.c @@ -197,7 +197,6 @@ void gint_world_leave(void) int gint_world_switch(gint_call_t call) { - extern void *gint_stack_top; gint_world_enter(GINT_WORLD_OS); void *ILRAM = (void *)0xe5200000; @@ -205,6 +204,7 @@ int gint_world_switch(gint_call_t call) void *YRAM = (void *)0xe5010000; /* Watch out for stack overflows */ + extern void *gint_stack_top; uint32_t *canary = gint_stack_top; if(canary) *canary = 0xb7c0ffee;