From bad0dbd5f400bd8272b11f7bc02d3ee5fc674cca Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Sat, 5 Apr 2025 09:31:38 +0200 Subject: [PATCH] fygue: support stat for directory and file --- CMakeLists.txt | 3 ++ src/fs/fygue/fat/fat.h | 40 ++++++++++++++++++- src/fs/fygue/fat/fat_dir_read.c | 2 +- src/fs/fygue/fat/fat_dir_stat.c | 66 ++++++++++++++++++++++++++++++++ src/fs/fygue/fat/fat_file_stat.c | 61 +++++++++++++++++++++++++++++ src/fs/fygue/fat/initialize.c | 2 + src/fs/fygue/fat/resolve.c | 27 ++++++++----- src/fs/fygue/fygue.c | 2 +- src/fs/fygue/fygue_open.c | 4 +- src/fs/fygue/fygue_stat.c | 36 +++++++++++++++++ 10 files changed, 227 insertions(+), 16 deletions(-) create mode 100644 src/fs/fygue/fat/fat_dir_stat.c create mode 100644 src/fs/fygue/fat/fat_file_stat.c create mode 100644 src/fs/fygue/fygue_stat.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d021385..1a68690 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_stat.c src/fs/fygue/fygue_dir_read.c src/fs/fygue/fygue_dir_lseek.c src/fs/fygue/fygue_dir_write.c @@ -271,6 +272,8 @@ set(SOURCES src/fs/fygue/fat/initialize.c src/fs/fygue/fat/fat_dir_read.c src/fs/fygue/fat/fat_dir_close.c + src/fs/fygue/fat/fat_dir_stat.c + src/fs/fygue/fat/fat_file_stat.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 dc0af07..977f99d 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -2,6 +2,7 @@ #define FS_FYGUE_FAT_H 1 #include +#include #include "../flash/flash.h" @@ -17,6 +18,14 @@ | (((x) & 0x000000ff) << 24) \ ) +/* FYGUE_FAT_ATTR_* : FAT dirent attribute */ +#define FYGUE_FAT_ATTR_READ_ONLY 0x01 +#define FYGUE_FAT_ATTR_HIDDEN 0x02 +#define FYGUE_FAT_ATTR_SYSTEM 0x04 +#define FYGUE_FAT_ATTR_VOLUME 0x08 +#define FYGUE_FAT_ATTR_DIRECTORY 0x10 +#define FYGUE_FAT_ATTR_ARCHIVE 0x20 + /* fygue_fat - fat information */ struct fygue_fat { @@ -26,6 +35,8 @@ struct fygue_fat } Type; int SectorHiddenCount; int SectorCount; + int SectorSize; + int SectorPerClus; int ClusterCount; int TotalCapacity; int RootEntCount; @@ -47,10 +58,10 @@ struct fygue_fat struct fygue_fat_dirent { char name[256]; - int type; size_t size; uintptr_t meta_addr; unsigned int cluster_id; + int attribute; }; /* fygue_fat_dir - fygue directory information */ @@ -65,12 +76,15 @@ struct fygue_fat_dir uintptr_t dirent_current_addr; bool end_of_dirent; bool dirty; + int attribute; }; /* fygue_fat_file: file information needed to perform IO primitives */ struct fygue_fat_file { - int todo; + int cluster_entry; + int attribute; + size_t size; }; /* fygue_fat_resolve: internal resolve information */ @@ -99,6 +113,10 @@ extern int fygue_fat_resolve( struct fygue_fat_resolve *resolve ); +//--- +// Directory interface +//--- + /* fygue_fat_dir_read(): readdir primitive */ extern int fygue_fat_dir_read( struct fygue_fat *fat, @@ -112,6 +130,24 @@ extern int fygue_fat_dir_close( struct fygue_fat_dir *dir ); +/* fygue_fat_dir_stat(): directory stat primitive */ +extern int fygue_fat_dir_stat( + struct fygue_fat *fat, + struct fygue_fat_dir *dir, + struct stat *statbuf +); + +//--- +// File interface +//--- + +/* fygue_fat_file_stat(): directory stat primitive */ +extern int fygue_fat_file_stat( + struct fygue_fat *fat, + struct fygue_fat_file *file, + struct stat *statbuf +); + //--- // Cluster interface //--- diff --git a/src/fs/fygue/fat/fat_dir_read.c b/src/fs/fygue/fat/fat_dir_read.c index 24333fd..fdd661c 100644 --- a/src/fs/fygue/fat/fat_dir_read.c +++ b/src/fs/fygue/fat/fat_dir_read.c @@ -155,7 +155,7 @@ static void _fygue_fat_readdir_dirent_gen( while (finfo->idx > 0) current->name[idx++] = finfo->filename[--finfo->idx]; current->name[idx] = 0x00; - current->type = dirent->DIR_Attr; + current->attribute = dirent->DIR_Attr; current->size = FAT_DWORD(dirent->DIR_FileSize); current->meta_addr = (uintptr_t)dirent; current->cluster_id = ( diff --git a/src/fs/fygue/fat/fat_dir_stat.c b/src/fs/fygue/fat/fat_dir_stat.c new file mode 100644 index 0000000..cbd3e5a --- /dev/null +++ b/src/fs/fygue/fat/fat_dir_stat.c @@ -0,0 +1,66 @@ +#include +#include "fat.h" + +//--- +// Internals +//--- + +/* _get_mode(): get "pseudo" file mode */ +static mode_t _get_mode(struct fygue_fat_dir *dir) +{ + mode_t mode; + + mode = 0777; + if (dir->attribute & FYGUE_FAT_ATTR_READ_ONLY) + mode = 0444; + if (dir->attribute & FYGUE_FAT_ATTR_DIRECTORY) + return mode | S_IFDIR; + return S_IFREG | 0777; +} + +/* _get_block_size(): return one cluster size */ +static int _get_block_size(struct fygue_fat *fat) +{ + return (fat->SectorSize * fat->SectorPerClus); +} + +/* _get_block_nb(): count the number of cluster */ +static int _get_block_nb(struct fygue_fat *fat, int cluster) +{ + int count; + + count = 0; + while (fygue_fat_cluster_get_next(fat, &cluster) == 0) + count += 1; + return count; +} + +//--- +// Public +//--- + +/* fygue_fat_dir_stat(): directory-specific stat primitive */ +int fygue_fat_dir_stat( + struct fygue_fat *fat, + struct fygue_fat_dir *dir, + struct stat *statbuf +) { + if (fat == NULL || dir == NULL || statbuf == NULL) { + errno = EIO; + return -1; + } + statbuf->st_dev = 0; /* not supported */ + statbuf->st_ino = dir->cluster_entry; + statbuf->st_mode = _get_mode(dir); + statbuf->st_nlink = 0; /* not supported */ + statbuf->st_uid = 0; /* not supported */ + statbuf->st_gid = 0; /* not supported */ + statbuf->st_rdev = 0; /* not supported */ + statbuf->st_size = 0; + statbuf->st_atime = 0; /* not supported */ + statbuf->st_mtime = 0; /* not supported */ + statbuf->st_ctime = 0; /* not supported */ + statbuf->st_blksize = _get_block_size(fat); + statbuf->st_blocks = _get_block_nb(fat, dir->cluster_entry); + return 0; +} diff --git a/src/fs/fygue/fat/fat_file_stat.c b/src/fs/fygue/fat/fat_file_stat.c new file mode 100644 index 0000000..21cb6bf --- /dev/null +++ b/src/fs/fygue/fat/fat_file_stat.c @@ -0,0 +1,61 @@ +#include +#include "fat.h" + +//--- +// Internals +//--- + +/* _get_mode(): get "pseudo" file mode */ +static mode_t _get_mode(int attribute) +{ + if (attribute & FYGUE_FAT_ATTR_READ_ONLY) + return S_IFDIR | 0444; + return S_IFDIR | 0777; +} + +/* _get_block_size(): return one cluster size */ +static int _get_block_size(struct fygue_fat *fat) +{ + return (fat->SectorSize * fat->SectorPerClus); +} + +/* _get_block_nb(): count the number of cluster */ +static int _get_block_nb(struct fygue_fat *fat, int cluster) +{ + int count; + + count = 1; + while (fygue_fat_cluster_get_next(fat, &cluster) == 0) + count += 1; + return count; +} + +//--- +// Public +//--- + +/* fygue_fat_file_stat(): directory-specific stat primitive */ +int fygue_fat_file_stat( + struct fygue_fat *fat, + struct fygue_fat_file *file, + struct stat *statbuf +) { + if (fat == NULL || file == NULL || statbuf == NULL) { + errno = EIO; + return -1; + } + statbuf->st_dev = 0; /* not supported */ + statbuf->st_ino = file->cluster_entry; + statbuf->st_mode = _get_mode(file->attribute); + statbuf->st_nlink = 0; /* not supported */ + statbuf->st_uid = 0; /* not supported */ + statbuf->st_gid = 0; /* not supported */ + statbuf->st_rdev = 0; /* not supported */ + statbuf->st_size = file->size; + statbuf->st_atime = 0; /* not supported */ + statbuf->st_mtime = 0; /* not supported */ + statbuf->st_ctime = 0; /* not supported */ + statbuf->st_blksize = _get_block_size(fat); + statbuf->st_blocks = _get_block_nb(fat, file->cluster_entry); + return 0; +} diff --git a/src/fs/fygue/fat/initialize.c b/src/fs/fygue/fat/initialize.c index d4d24ea..e16e9ed 100644 --- a/src/fs/fygue/fat/initialize.c +++ b/src/fs/fygue/fat/initialize.c @@ -127,6 +127,8 @@ static int _fygue_fat_configure(struct fygue_fat *fat) fat->TotalCapacity = DataSec * FAT_WORD(bpb->BPB_BytsPerSec); fat->RootEntCount = FAT_WORD(bpb->BPB_RootEntCnt); + fat->SectorSize = FAT_WORD(bpb->BPB_BytsPerSec); + fat->SectorPerClus = bpb->BPB_SecPerClus; // todo : FAT12-specific operation fat->ClusterCount = FAT_WORD(bpb->BPB_FATSz16); diff --git a/src/fs/fygue/fat/resolve.c b/src/fs/fygue/fat/resolve.c index 8c0bb2a..af458d1 100644 --- a/src/fs/fygue/fat/resolve.c +++ b/src/fs/fygue/fat/resolve.c @@ -36,15 +36,18 @@ static int _fygue_dirent_resolve( struct fygue_fat_dir *dir, struct fygue_fat_dirent *dirent ) { + int rc; + memset(dir, 0x00, sizeof(struct fygue_fat_dir)); - if (dirent == NULL) - { + if (dirent == NULL) { dir->cluster_entry = 0; dir->root_dirent_count = fat->RootEntCount; + dir->attribute = FYGUE_FAT_FILE_TYPE_DIR; } else { - if ((dirent->type & 0x10) == 0x00) + if ((dirent->attribute & FYGUE_FAT_FILE_TYPE_DIR) == 0x00) return -1; dir->cluster_entry = dirent->cluster_id; + dir->attribute = FYGUE_FAT_FILE_TYPE_DIR; dir->root_dirent_count = 0; } dir->dirty = false; @@ -52,18 +55,19 @@ static int _fygue_dirent_resolve( dir->dirent_cursor = 0; dir->end_of_dirent = false; dir->cluster_current = dir->cluster_entry; - int rc = fygue_fat_cluster_get_sector( + rc = fygue_fat_cluster_get_sector( fat, dir->cluster_current, &dir->sector_id ); if (rc != 0) - return -1; - return fygue_fat_sector_get_addr( + return -2; + rc = fygue_fat_sector_get_addr( fat, &dir->dirent_current_addr, dir->sector_id ); + return (rc != 0) ? -3 : 0; } /* _fygue_opendir_find() - try to find the directory entry */ @@ -90,11 +94,14 @@ static int _fygue_resolve_set( struct fygue_fat_resolve *resolve, struct fygue_fat_dirent *dirent ) { - resolve->type = FYGUE_FAT_FILE_TYPE_DIR; - if (_fygue_dirent_resolve(fat, &(resolve->dir), dirent) == 0) - return 0; + if (dirent == NULL || (dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY)) { + resolve->type = FYGUE_FAT_FILE_TYPE_DIR; + return _fygue_dirent_resolve(fat, &(resolve->dir), dirent); + } resolve->type = FYGUE_FAT_FILE_TYPE_FILE; - // todo: support IO file information + resolve->file.attribute = dirent->attribute; + resolve->file.cluster_entry = dirent->cluster_id; + resolve->file.size = dirent->size; return 0; } diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index 377fdc8..169de06 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -55,7 +55,7 @@ int fygue_resolve(char const * const path, struct fygue_resolve *resolve) return -1; if (fygue_mount(&fsinfo, true) != 0) return -2; - if (fygue_fat_resolve(&(fsinfo->fat), path, &fat_resolve) < 0) + 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) diff --git a/src/fs/fygue/fygue_open.c b/src/fs/fygue/fygue_open.c index 0093f90..c25b4c2 100644 --- a/src/fs/fygue/fygue_open.c +++ b/src/fs/fygue/fygue_open.c @@ -24,7 +24,7 @@ int fygue_open(char const *path, int flags, GUNUSED mode_t mode) /* if opening fails and no explicit file creation is required, fail */ if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY)))) { errno = ENOENT; - return exists; + return -1; } /* if opening fails and the previous check as not returned an error, @@ -32,7 +32,7 @@ int fygue_open(char const *path, int flags, GUNUSED mode_t mode) * file-system, so, fail */ if (exists < 0) { errno = EROFS; - return exists; + return -1; } /* If the entry exists and O_EXCL was requested, fail. diff --git a/src/fs/fygue/fygue_stat.c b/src/fs/fygue/fygue_stat.c new file mode 100644 index 0000000..2028dd6 --- /dev/null +++ b/src/fs/fygue/fygue_stat.c @@ -0,0 +1,36 @@ +#include "fygue.h" +#include "fat/fat.h" + +/* fygue_stat(): stat primitive */ +int fygue_stat(char const * const path, struct stat *statbuf) +{ + struct fygue_resolve resolve; + struct fygue_fsinfo *fsinfo; + + ENOTSUP_IF_NOT_FYGUE(-1); + if (path == NULL || statbuf == NULL) { + errno = EFAULT; + return -1; + } + if (fygue_mount(&fsinfo, true) != 0) { + errno = EIO; + return -1; + } + + if (fygue_resolve(path, &resolve) != 0) { + errno = ENOENT; + return -1; + } + if (resolve.type == FYGUE_FILE_TYPE_DIR) { + fygue_fat_dir_stat( + &(fsinfo->fat), + &(resolve.dir.fat), + statbuf + ); + } + return fygue_fat_file_stat( + &(fsinfo->fat), + &(resolve.file.fat), + statbuf + ); +}