From dae09728782d92033853343a8884ec1f6cc398aa Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Fri, 4 Apr 2025 08:50:24 +0200 Subject: [PATCH] fygue: support readdir() + small fixes --- CMakeLists.txt | 1 + src/fs/fygue/fat/fat.h | 1 + src/fs/fygue/fat/resolve.c | 7 ---- src/fs/fygue/fygue.c | 9 ++--- src/fs/fygue/fygue.h | 25 ++++++------- src/fs/fygue/fygue_dir_read.c | 68 +++++++++++++++++++++++++++++++++++ src/fs/fygue/fygue_open.c | 4 +++ 7 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 src/fs/fygue/fygue_dir_read.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a3237a0..0e95cbf 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_dir_read.c src/fs/fygue/fat/cluster.c src/fs/fygue/fat/initialize.c src/fs/fygue/fat/readdir.c diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index 1f1e17e..a6e3fea 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -43,6 +43,7 @@ struct fygue_fat }; /* fygue_fat_dirent - FAT dirent information */ +//TODO: flexible name array like the high-level `struct dirent` ? struct fygue_fat_dirent { char name[256]; diff --git a/src/fs/fygue/fat/resolve.c b/src/fs/fygue/fat/resolve.c index 6f69faf..7db2d87 100644 --- a/src/fs/fygue/fat/resolve.c +++ b/src/fs/fygue/fat/resolve.c @@ -102,10 +102,6 @@ static int _fygue_resolve_set( // Public //--- -char const *debug_prefix = ""; -char const *debug_start = ""; -size_t debug_len = 0; - /* fygue_fat_resolve(): resolve any path provided * * notes @@ -138,9 +134,6 @@ int fygue_fat_resolve( is_root = false; continue; } - debug_prefix = prefix; - debug_start = start; - debug_len = len; if (_fygue_dirent_find(fat, &dir, &dirent, start, len) != 0) return -4; if (_fygue_path_get_name(&prefix, &start, &len) != 0) diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index 691e79a..51445b8 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -55,9 +55,9 @@ int fygue_resolve(char const * const path, struct fygue_resolve *resolve) return -1; if (fygue_mount(&fsinfo, true) != 0) return -2; - int rc = fygue_fat_resolve(&(fsinfo->fat), path, &fat_resolve); - if (rc < 0) - return rc; + if (fygue_fat_resolve(&(fsinfo->fat), path, &fat_resolve) < 0) + return -3; + memset(resolve, 0x00, sizeof(struct fygue_resolve)); if (fat_resolve.type == FYGUE_FAT_FILE_TYPE_FILE) { resolve->type = FYGUE_FILE_TYPE_DIR; @@ -69,6 +69,7 @@ int fygue_resolve(char const * const path, struct fygue_resolve *resolve) ); } else { resolve->type = FYGUE_FILE_TYPE_DIR; + resolve->dir.dirent = NULL; memcpy( &(resolve->dir.fat), &(fat_resolve.dir), @@ -90,7 +91,7 @@ const fs_descriptor_type_t fygue_descriptor_type = { }; const fs_descriptor_type_t fygue_dir_descriptor_type = { - .read = NULL, + .read = (void*)&fygue_dir_read, .write = NULL, .lseek = NULL, .close = NULL, diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h index f56e91f..16e9ae9 100644 --- a/src/fs/fygue/fygue.h +++ b/src/fs/fygue/fygue.h @@ -28,10 +28,7 @@ extern const fs_descriptor_type_t fygue_dir_descriptor_type; 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 * restrict path, - struct stat * restrict statbuf -); +extern int fygue_stat(char const *path, struct stat *statbuf); /* fygue_syncfs() - request filesystem re-synchronisation */ extern int fygue_syncfs(void *desc); @@ -43,14 +40,10 @@ extern int fygue_syncfs(void *desc); #include #include -#define ENOTSUP_IF_NOT_FYGUE(rc) \ - if( \ - (gint[HWFS] != HWFS_FUGUE) || \ - (flags & O_WRONLY) || \ - (flags & O_RDWR) \ - ) { \ - errno = ENOTSUP; \ - return (rc); \ +#define ENOTSUP_IF_NOT_FYGUE(rc) \ + if(gint[HWFS] != HWFS_FUGUE) { \ + errno = ENOTSUP; \ + return (rc); \ } #include "fat/fat.h" @@ -75,6 +68,7 @@ struct fygue_resolve { } file; struct { struct fygue_fat_dir fat; + struct dirent *dirent; } dir; }; }; @@ -98,6 +92,13 @@ extern int fygue_resolve( struct fygue_resolve *resolve ); +/* fygue_dir_read(): directory read implementation */ +extern int fygue_dir_read( + struct fygue_descriptor *desc, + struct dirent **dirent, + size_t size +); + #ifdef __cplusplus } #endif diff --git a/src/fs/fygue/fygue_dir_read.c b/src/fs/fygue/fygue_dir_read.c new file mode 100644 index 0000000..e73e9b7 --- /dev/null +++ b/src/fs/fygue/fygue_dir_read.c @@ -0,0 +1,68 @@ +#include +#include +#include "fygue.h" + +/* fygue_dir_read(): directory read implementation + * + * notes + * - assume that the directory have read permission */ +int fygue_dir_read( + struct fygue_descriptor *desc, + struct dirent **dirent, + size_t size +) { + struct fygue_fat_dirent fat_dirent; + struct fygue_fsinfo *fsinfo; + size_t len; + int rc; + + ENOTSUP_IF_NOT_FYGUE(-1); + + if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { + errno = EBADF; + return -1; + } + if (dirent == NULL) { + errno = EFAULT; + return -1; + } + if (size < sizeof *dirent) { + errno = EINVAL; + return -1; + } + if (fygue_mount(&fsinfo, true) != 0) { + errno = EIO; + return -1; + } + + /* get the next FAT dirent */ + rc = fygue_fat_readdir( + &(fsinfo->fat), + &desc->resolve.dir.fat, + &fat_dirent + ); + if (rc <= -3) + return 0; + if (rc < 0) { + errno = EIO; + return -1; + } + + /* since `struct dirent` use flexible array to store the filename + * we need to reallocate the buffer each time */ + //FIXME: ensure UTF-8/SHIFT-JS + len = strlen(fat_dirent.name); + *dirent = desc->resolve.dir.dirent; + *dirent = realloc(*dirent, sizeof(struct dirent) + len + 2); + if (*dirent == NULL) { + errno = ENOMEM; + return -1; + } + + /* convert FAT dirent into generic dirent information */ + //FIXME: ensure UTF-8/SHIFT-JS + (*dirent)->d_ino = fat_dirent.cluster_id; + (*dirent)->d_type = DT_REG; + memcpy((*dirent)->d_name, fat_dirent.name, len + 1); + return 0; +} diff --git a/src/fs/fygue/fygue_open.c b/src/fs/fygue/fygue_open.c index 8011574..0093f90 100644 --- a/src/fs/fygue/fygue_open.c +++ b/src/fs/fygue/fygue_open.c @@ -12,6 +12,10 @@ int fygue_open(char const *path, int flags, GUNUSED mode_t mode) struct fygue_resolve resolve; fs_descriptor_t data; + if ((flags & O_RDWR) || (flags & O_WRONLY)) { + errno = EROFS; + return -1; + } ENOTSUP_IF_NOT_FYGUE(-1); /* resolve the entry */