diff --git a/CMakeLists.txt b/CMakeLists.txt index 34e2c03..bb6185d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,31 +264,38 @@ set(SOURCES src/fs/fygue/fygue_open.c src/fs/fygue/fygue_syncfs.c src/fs/fygue/fygue_stat.c + src/fs/fygue/fygue_mount.c + src/fs/fygue/fygue_dir_open.c src/fs/fygue/fygue_dir_read.c - src/fs/fygue/fygue_dir_lseek.c src/fs/fygue/fygue_dir_write.c + src/fs/fygue/fygue_dir_lseek.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/fygue_file_close.c + src/fs/fygue/fygue_dir_sync.c + src/fs/fygue/fygue_file_open.c src/fs/fygue/fygue_file_read.c - src/fs/fygue/fat/cluster.c + src/fs/fygue/fygue_file_write.c + src/fs/fygue/fygue_file_lseek.c + src/fs/fygue/fygue_file_close.c + src/fs/fygue/fygue_file_sync.c src/fs/fygue/fat/fat.c + src/fs/fygue/fat/cluster.c + src/fs/fygue/fat/sector.c src/fs/fygue/fat/fat_dir_open.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_dir_close.c + src/fs/fygue/fat/fat_dir_sync.c src/fs/fygue/fat/fat_file_open.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 - src/fs/fygue/flash/cmap.c - src/fs/fygue/flash/flash.c - src/fs/fygue/flash/sector.c + src/fs/fygue/fat/fat_file_stat.c + src/fs/fygue/fat/fat_file_close.c + src/fs/fygue/fat/fat_file_sync.c + src/fs/fygue/fat/fat_open.c + src/fs/fygue/fat/flash/cluster.c + src/fs/fygue/fat/flash/cmap.c + src/fs/fygue/fat/flash/flash.c + src/fs/fygue/fat/flash/sector.c ) set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png) diff --git a/src/fs/fs.c b/src/fs/fs.c index 8b96d76..d6b4a78 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -60,7 +60,7 @@ bool fs_descriptor_is_fygue(fs_descriptor_t const *desc) { return ( (desc->type == &fygue_dir_descriptor_type) || - (desc->type == &fygue_descriptor_type) + (desc->type == &fygue_file_descriptor_type) ); } diff --git a/src/fs/fygue/fat/cluster.c b/src/fs/fygue/fat/cluster.c index 6898c49..71f11a0 100644 --- a/src/fs/fygue/fat/cluster.c +++ b/src/fs/fygue/fat/cluster.c @@ -2,7 +2,7 @@ ** fygue/fat/cluster - FAT cluster handling */ #include "fat.h" -#include "../flash/flash.h" +#include "flash/flash.h" //--- // Internals diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index 4701440..c69f9b8 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -4,14 +4,14 @@ #include #include -#include "../flash/flash.h" +#include "flash/flash.h" /* _FAT_WORD() : helper for 16bit value */ #define FAT_WORD(x) \ (((x & 0xff00) >> 8) | ((x & 0x00ff) << 8)) /* _FAT_DWORD() : helper for 32bit value */ -#define FAT_DWORD(x) ( \ +#define FAT_DWORD(x) ( \ (((x) & 0xff000000) >> 24) \ | (((x) & 0x00ff0000) >> 8) \ | (((x) & 0x0000ff00) << 8) \ @@ -94,12 +94,12 @@ struct fygue_fat_file int chunk_rd_offset; }; -/* fygue_fat_resolve: internal resolve information */ -struct fygue_fat_resolve +/* fygue_fat_descriptor: FAT descriptor information */ +struct fygue_fat_descriptor { enum { - FYGUE_FAT_FILE_TYPE_FILE, - FYGUE_FAT_FILE_TYPE_DIR, + FYGUE_FAT_DESC_TYPE_FILE, + FYGUE_FAT_DESC_TYPE_DIR, } type; union { struct fygue_fat_file file; @@ -107,17 +107,21 @@ struct fygue_fat_resolve }; }; +//--- +// Public interface +//--- + /* fygue_fat_initialize() - fully initialize the FAT information */ extern int fygue_fat_initialize(struct fygue_fat *fat); /* fygue_fat_sync() - re-initialize the FAT information */ extern int fygue_fat_sync(struct fygue_fat *fat); -/* fygue_fat_resolve() - resolve the path and set the dirent information */ -extern int fygue_fat_resolve( +/* fygue_fat_open() - resolve the path and set the dirent information */ +extern int fygue_fat_open( struct fygue_fat *fat, char const * const path, - struct fygue_fat_resolve *resolve + struct fygue_fat_descriptor *desc ); //--- @@ -154,7 +158,8 @@ extern int fygue_fat_dir_stat( /* fygue_fat_dir_sync(): sync directory information */ extern int fygue_fat_dir_sync( struct fygue_fat *fat, - struct fygue_fat_dir *dir + struct fygue_fat_dir *dir, + int cluster_id ); //--- @@ -199,7 +204,8 @@ extern int fygue_fat_file_close( /* fygue_fat_file_sync(): sync internal information */ extern int fygue_fat_file_sync( struct fygue_fat *fat, - struct fygue_fat_file *file + struct fygue_fat_file *file, + int cluster_id ); //--- diff --git a/src/fs/fygue/fat/fat_dir_open.c b/src/fs/fygue/fat/fat_dir_open.c index 0c43768..1a4221c 100644 --- a/src/fs/fygue/fat/fat_dir_open.c +++ b/src/fs/fygue/fat/fat_dir_open.c @@ -7,38 +7,17 @@ int fygue_fat_dir_open( struct fygue_fat_dir *dir, struct fygue_fat_dirent *dirent ) { - int rc; - memset(dir, 0x00, sizeof(struct fygue_fat_dir)); if (dirent == NULL) { dir->cluster_entry = 0; dir->root_dirent_count = fat->RootEntCount; - dir->attribute = FYGUE_FAT_FILE_TYPE_DIR; + dir->attribute = FYGUE_FAT_DESC_TYPE_DIR; } else { - if ((dirent->attribute & FYGUE_FAT_FILE_TYPE_DIR) == 0x00) + if ((dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY) == 0x00) return -1; dir->cluster_entry = dirent->cluster_id; - dir->attribute = FYGUE_FAT_FILE_TYPE_DIR; + dir->attribute = FYGUE_FAT_DESC_TYPE_DIR; dir->root_dirent_count = 0; } - dir->dirty = false; - dir->sector_count = 0; - dir->dirent_cursor = 0; - dir->end_of_dirent = false; - dir->cluster_current = dir->cluster_entry; - rc = fygue_fat_cluster_get_sector( - fat, - dir->cluster_current, - &dir->sector_id - ); - if (rc != 0) - return -2; - rc = fygue_fat_sector_get_addr( - fat, - &dir->dirent_current_addr, - dir->sector_id - ); - if (rc != 0) - return -3; - return 0; + return fygue_fat_dir_sync(fat, dir, dir->cluster_entry); } diff --git a/src/fs/fygue/fat/fat_dir_sync.c b/src/fs/fygue/fat/fat_dir_sync.c index 8f2761a..956c7e0 100644 --- a/src/fs/fygue/fat/fat_dir_sync.c +++ b/src/fs/fygue/fat/fat_dir_sync.c @@ -3,10 +3,32 @@ /* fygue_fat_dir_sync(): sync directory information */ int fygue_fat_dir_sync( struct fygue_fat *fat, - struct fygue_fat_dir *dir + struct fygue_fat_dir *dir, + int cluster_id ) { + int rc; + if (fat == NULL || dir == NULL) return -1; - // nothing to do (?) + dir->dirty = false; + dir->sector_count = 0; + dir->dirent_cursor = 0; + dir->end_of_dirent = false; + dir->cluster_entry = cluster_id; + dir->cluster_current = dir->cluster_entry; + rc = fygue_fat_cluster_get_sector( + fat, + dir->cluster_current, + &dir->sector_id + ); + if (rc != 0) + return -2; + rc = fygue_fat_sector_get_addr( + fat, + &dir->dirent_current_addr, + dir->sector_id + ); + if (rc != 0) + return -3; return 0; } diff --git a/src/fs/fygue/fat/fat_file_open.c b/src/fs/fygue/fat/fat_file_open.c index b0f4de7..4d93da1 100644 --- a/src/fs/fygue/fat/fat_file_open.c +++ b/src/fs/fygue/fat/fat_file_open.c @@ -15,7 +15,7 @@ int fygue_fat_file_open( file->chunk = NULL; file->chunk_count = 0; file->chunk_table_max_index = 0; - if (fygue_fat_file_sync(fat, file) != 0) + if (fygue_fat_file_sync(fat, file, dirent->cluster_id) != 0) return -1; if (fygue_fat_file_seek(fat, file, 0) != 0) return -2; diff --git a/src/fs/fygue/fat/fat_file_sync.c b/src/fs/fygue/fat/fat_file_sync.c index 0adda80..be54062 100644 --- a/src/fs/fygue/fat/fat_file_sync.c +++ b/src/fs/fygue/fat/fat_file_sync.c @@ -60,15 +60,15 @@ static int _fygue_chunk_error(struct fygue_fat_file *file) /* fygue_fat_file_sync(): sync internal information */ int fygue_fat_file_sync( struct fygue_fat *fat, - struct fygue_fat_file *file + struct fygue_fat_file *file, + int cluster_id ) { uintptr_t cluster_addr; - int cluster_id; if (fat == NULL || file == NULL) return -1; file->chunk_count = 0; - cluster_id = file->cluster_entry; + file->cluster_entry = cluster_id; while (true) { if (fygue_fat_cluster_get_addr(fat, &cluster_addr, cluster_id) != 0) diff --git a/src/fs/fygue/fat/resolve.c b/src/fs/fygue/fat/fat_open.c similarity index 82% rename from src/fs/fygue/fat/resolve.c rename to src/fs/fygue/fat/fat_open.c index 73f8bc2..9ab2d16 100644 --- a/src/fs/fygue/fat/resolve.c +++ b/src/fs/fygue/fat/fat_open.c @@ -52,15 +52,16 @@ static int _fygue_dirent_find( /* _fygue_resolve_set(): setup the resolve response */ static int _fygue_resolve_set( struct fygue_fat *fat, - struct fygue_fat_resolve *resolve, + struct fygue_fat_descriptor *desc, struct fygue_fat_dirent *dirent ) { if (dirent == NULL || (dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY)) { - resolve->type = FYGUE_FAT_FILE_TYPE_DIR; - return fygue_fat_dir_open(fat, &(resolve->dir), dirent); + desc->type = FYGUE_FAT_DESC_TYPE_DIR; + return fygue_fat_dir_open(fat, &(desc->dir), dirent); + } else { + desc->type = FYGUE_FAT_DESC_TYPE_FILE; + return fygue_fat_file_open(fat, &(desc->file), dirent); } - resolve->type = FYGUE_FAT_FILE_TYPE_FILE; - return fygue_fat_file_open(fat, &(resolve->file), dirent); } //--- @@ -71,10 +72,10 @@ static int _fygue_resolve_set( * * notes * - assume that the path is clean */ -int fygue_fat_resolve( +int fygue_fat_open( struct fygue_fat *fat, char const * const path, - struct fygue_fat_resolve *resolve + struct fygue_fat_descriptor *desc ) { struct fygue_fat_dirent dirent; struct fygue_fat_dir dir; @@ -83,7 +84,7 @@ int fygue_fat_resolve( size_t len; bool is_root; - if (fat == NULL || path == NULL || resolve == NULL) + if (fat == NULL || path == NULL || desc == NULL) return -1; if (path[0] != '/') return -1; @@ -107,6 +108,6 @@ int fygue_fat_resolve( return -5; } if (is_root) - return _fygue_resolve_set(fat, resolve, NULL); - return _fygue_resolve_set(fat, resolve, &dirent); + return _fygue_resolve_set(fat, desc, NULL); + return _fygue_resolve_set(fat, desc, &dirent); } diff --git a/src/fs/fygue/flash/cluster.c b/src/fs/fygue/fat/flash/cluster.c similarity index 100% rename from src/fs/fygue/flash/cluster.c rename to src/fs/fygue/fat/flash/cluster.c diff --git a/src/fs/fygue/flash/cmap.c b/src/fs/fygue/fat/flash/cmap.c similarity index 100% rename from src/fs/fygue/flash/cmap.c rename to src/fs/fygue/fat/flash/cmap.c diff --git a/src/fs/fygue/flash/flash.c b/src/fs/fygue/fat/flash/flash.c similarity index 100% rename from src/fs/fygue/flash/flash.c rename to src/fs/fygue/fat/flash/flash.c diff --git a/src/fs/fygue/flash/flash.h b/src/fs/fygue/fat/flash/flash.h similarity index 100% rename from src/fs/fygue/flash/flash.h rename to src/fs/fygue/fat/flash/flash.h diff --git a/src/fs/fygue/flash/sector.c b/src/fs/fygue/fat/flash/sector.c similarity index 100% rename from src/fs/fygue/flash/sector.c rename to src/fs/fygue/fat/flash/sector.c diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index 72577b2..d13366f 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -1,129 +1,171 @@ #include #include +#include #include "fygue.h" //--- // Internals //--- -/* __fygue_fsinfo: internal filesystem information */ -static struct fygue_fsinfo *__fygue_fsinfo = NULL; +/* FYGUE_GFDI_CHEK - shorthand for all GFDI prologue */ +#define FYGUE_GFDI_CHEK(type) \ + _fygue_gfdi_ensure_valid(&fsinfo, desc, type) -//--- -// Primitives -//--- - -/* fygue_mount() - mount (if needed) and return the filesystem information +/* _fygue_gfdi_ensure_valid(): ensure GFDI validity * - * notes - * - assume that this global is const after initialisation */ -int fygue_mount(struct fygue_fsinfo **fsinfo, bool refresh) -{ - if (fsinfo == NULL) - return -1; - *fsinfo = NULL; - if (__fygue_fsinfo == NULL) - { - __fygue_fsinfo = calloc(1, sizeof(struct fygue_fsinfo)); - if (__fygue_fsinfo == NULL) - return -2; - if (fygue_fat_initialize(&(__fygue_fsinfo->fat)) != 0) { - free(__fygue_fsinfo); - __fygue_fsinfo = NULL; - return -3; - } - __fygue_fsinfo->dirty = false; - } - if (refresh && __fygue_fsinfo->dirty) { - if (fygue_fat_sync(&(__fygue_fsinfo->fat)) != 0) - return -4; - __fygue_fsinfo->dirty = false; - } - *fsinfo = __fygue_fsinfo; - return 0; -} - -/* fygue_resolve() - try to resolve path - * - * notes - * - assume that path is clean - * - automatically mount the filesystem if needed - * - the saved pathname will not be saved in stat */ -int fygue_resolve(char const * const path, struct fygue_resolve *resolve) -{ - struct fygue_fsinfo *fsinfo; - struct fygue_fat_resolve fat_resolve; - - if (path == NULL || path[0] != '/' || resolve == NULL) - return -1; - if (fygue_mount(&fsinfo, true) != 0) - return -2; - 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; - resolve->file.cursor = 0; - memcpy( - &(resolve->file.fat), - &(fat_resolve.file), - sizeof(struct fygue_fat_file) - ); - } else { - resolve->type = FYGUE_FILE_TYPE_DIR; - resolve->dir.dirent = NULL; - memcpy( - &(resolve->dir.fat), - &(fat_resolve.dir), - sizeof(struct fygue_fat_dir) - ); - } - return 0; -} - -//--- -// Syncronization -//--- - -/* fygue_descriptor_sync(): sync internal descriptor information */ -int fygue_descriptor_sync( + * notes: + * - assume info is not NULL + * - auto mount the FS (if needed) and get information + * - ensure file sync if needed */ +static int _fygue_gfdi_ensure_valid( struct fygue_fsinfo **fsinfo, - struct fygue_descriptor *desc + struct fygue_descriptor *desc, + unsigned int type ) { - int (*sync)(struct fygue_descriptor*); - struct fygue_fsinfo *ffsinfo; + int rc; - if (fygue_mount(&ffsinfo, true) != 0) - return -2; - if (fsinfo != NULL) - *fsinfo = ffsinfo; - if (desc != NULL && desc->dirty) + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); + if (fsinfo == NULL) + FYGUE_RET_ERRNO(EIO); + if (desc == NULL || desc->type == type) + FYGUE_RET_ERRNO(EBADF); + if (fygue_mount(fsinfo) != 0) + FYGUE_RET_ERRNO(EIO); + if (desc->dirty) { - sync = &fygue_file_sync; - if (desc->resolve.type == FYGUE_FILE_TYPE_DIR) - sync = &fygue_dir_sync; - if (sync(desc) != 0) - return -1; + if (desc->type == FYGUE_DESC_TYPE_DIR) + rc = fygue_dir_sync(*fsinfo, &(desc->dir)); + if (desc->type == FYGUE_DESC_TYPE_FILE) + rc = fygue_file_sync(*fsinfo, &(desc->file)); + if (rc != 0) + FYGUE_RET_ERRNO(EIO); desc->dirty = false; } return 0; } +//--- +// Gint File Descriptor Interface (gfdi) for file +//--- + +/* fygue_gfdi_file_write(): write file */ +static ssize_t fygue_gfdi_file_write( + struct fygue_descriptor *desc, + void *buffer, + size_t size +) { + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0) + return fygue_file_write(fsinfo, &(desc->file), buffer, size); + return -1; +} + +/* fygue_gfdi_file_read(): write directory (EISDIR) */ +static ssize_t fygue_gfdi_file_read( + struct fygue_descriptor *desc, + void *buffer, + size_t size +) { + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0) + return fygue_file_read(fsinfo, &(desc->file), buffer, size); + return -1; +} + +/* fygue_file_lseek(): seek file */ +static off_t fygue_gfdi_file_lseek( + struct fygue_descriptor *desc, + off_t offset, + int whence +) { + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0) + return fygue_file_lseek(fsinfo, &(desc->file), offset, whence); + return -1; +} + +/* fygue_file_close(): close directory */ +static int fygue_gfdi_file_close(struct fygue_descriptor *desc) +{ + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0) + return fygue_file_close(fsinfo, &(desc->file)); + return -1; +} + +//--- +// Gint File Descriptor Interface (gfdi) for file +//--- + +/* fygue_dir_write(): write directory (EISDIR) */ +ssize_t fygue_gfdi_dir_write( + struct fygue_descriptor *desc, + void *buffer, + size_t size +) { + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0) + return fygue_dir_write(fsinfo, &(desc->dir), buffer, size); + return -1; +} + +/* fygue_gfdi_dir_read(): readdir */ +ssize_t fygue_gfdi_dir_read( + struct fygue_descriptor *desc, + struct dirent **dirent, + size_t size +) { + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0) + return fygue_dir_read(fsinfo, &(desc->dir), dirent, size); + return -1; +} + +/* fygue_gfdi_dir_lseek(): seek directory */ +off_t fygue_gfdi_dir_lseek( + struct fygue_descriptor *desc, + off_t offset, + int whence +) { + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0) + return fygue_dir_lseek(fsinfo, &(desc->dir), offset, whence); + return -1; +} + +/* fygue_gfdi_dir_close(): close directory */ +int fygue_gfdi_dir_close(struct fygue_descriptor *desc) +{ + struct fygue_fsinfo *fsinfo; + + if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0) + return fygue_dir_close(fsinfo, &(desc->dir)); + return -1; +} + //--- // Descriptor //--- -const fs_descriptor_type_t fygue_descriptor_type = { - .read = (void*)&fygue_file_read, - .write = (void*)&fygue_file_write, - .lseek = (void*)&fygue_file_lseek, - .close = (void*)&fygue_file_close, +/* fygue_file_descriptor_type - fygue file descriptor */ +const fs_descriptor_type_t fygue_file_descriptor_type = { + .read = (void*)&fygue_gfdi_file_read, + .write = (void*)&fygue_gfdi_file_write, + .lseek = (void*)&fygue_gfdi_file_lseek, + .close = (void*)&fygue_gfdi_file_close, }; 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 = (void*)&fygue_dir_close, + .read = (void*)&fygue_gfdi_dir_read, + .write = (void*)&fygue_gfdi_dir_write, + .lseek = (void*)&fygue_gfdi_dir_lseek, + .close = (void*)&fygue_gfdi_dir_close, }; diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h index d8ae317..f2e89e6 100644 --- a/src/fs/fygue/fygue.h +++ b/src/fs/fygue/fygue.h @@ -10,13 +10,15 @@ extern "C" { #include #include #include +#include +#include "fat/fat.h" //--- // Public global //--- /* File descriptor type */ -extern const fs_descriptor_type_t fygue_descriptor_type; +extern const fs_descriptor_type_t fygue_file_descriptor_type; /* Directory descriptor type */ extern const fs_descriptor_type_t fygue_dir_descriptor_type; @@ -24,29 +26,9 @@ extern const fs_descriptor_type_t fygue_dir_descriptor_type; // Public (low-level) API //--- -/* fygue_open() - open file or directory */ -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 */ -extern int fygue_syncfs(void *desc); - -//--- -// Internals -//--- - -#include -#include - -#define ENOTSUP_IF_NOT_FYGUE(rc) \ - if(gint[HWFS] != HWFS_FUGUE) { \ - errno = ENOTSUP; \ - return (rc); \ - } - -#include "fat/fat.h" +/* helper to set errno and return -1 */ +#define FYGUE_RET_ERRNO(error) \ + do { errno = error; return -1; } while(0); /* fygue_fsinfo: internal fygue FS information */ struct fygue_fsinfo @@ -55,111 +37,162 @@ struct fygue_fsinfo bool dirty; }; -/* fygue_resolve: internals file information */ -struct fygue_resolve { - enum { - FYGUE_FILE_TYPE_FILE, - FYGUE_FILE_TYPE_DIR, - } type; - union { - struct { - off_t cursor; - struct fygue_fat_file fat; - } file; - struct { - struct fygue_fat_dir fat; - struct dirent **dirent; - int count; - int pos; - } dir; - }; +/* fygue_open() - open file or directory */ +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 */ +extern int fygue_syncfs(void *data); + +/* fygue_mount() - mount the filesystem */ +extern int fygue_mount(struct fygue_fsinfo **fsinfo); + +//--- +// Internals +//--- + +/* fygue_file - file information */ +struct fygue_file +{ + struct fygue_fat_file fat; + off_t cursor; + size_t size; + char *path; }; -/* fygue_descriptor: internal file descriptor information */ +/* fygue_dir - directory information */ +struct fygue_dir +{ + struct fygue_fat_dir fat; + struct dirent **dirent; + int dirent_idx_max; + int count; + int pos; + char *path; +}; + +/* fygue_descriptor - fygue file descriptor */ struct fygue_descriptor { - struct fygue_resolve resolve; - char const *path; - int flags; + enum { + FYGUE_DESC_TYPE_FILE, + FYGUE_DESC_TYPE_DIR, + } type; + union { + struct fygue_file file; + struct fygue_dir dir; + }; bool dirty; }; -/* fygue_mount(): mount and return the filesystem info */ -extern int fygue_mount(struct fygue_fsinfo **fsinfo, bool refresh); +//--- +// Helper +//--- -/* fygue_descriptor_sync(): sync internal descriptor information */ -extern int fygue_descriptor_sync( - struct fygue_fsinfo **fsinfo, +/* fygue_open_resolve() - open file or directory */ +extern int fygue_open_resolve( + char const *path, struct fygue_descriptor *desc ); -/* fygue_resolve() - try to resolve path */ -extern int fygue_resolve( - char const * const path, - struct fygue_resolve *resolve -); - //--- // Directory interface //--- +/* fygue_dir_open(): directory-specific open */ +extern int fygue_dir_open( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, + char const * const path, + struct fygue_fat_dir *fat_dir +); + /* fygue_dir_read(): directory read implementation */ -extern int fygue_dir_read( - struct fygue_descriptor *desc, +extern ssize_t fygue_dir_read( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, struct dirent **dirent, size_t size ); /* fygue_dir_lseek(): seek directory */ extern off_t fygue_dir_lseek( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, off_t offset, int whence ); /* fygue_dir_write(): write directory (EISDIR) */ extern ssize_t fygue_dir_write( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, void *buffer, size_t size ); /* fygue_dir_close(): close directory */ -extern int fygue_dir_close(struct fygue_descriptor *desc); +extern int fygue_dir_close( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir +); /* fygue_dir_sync(): directory-specific sync */ -extern int fygue_dir_sync(struct fygue_descriptor *desc); +extern int fygue_dir_sync( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir +); //--- // File interface //--- +/* fygue_file_open(): file open */ +extern int fygue_file_open( + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, + char const * const path, + struct fygue_fat_file *fat_file +); + /* fygue_file_read(): read primitive */ extern ssize_t fygue_file_read( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, void *buffer, size_t size ); /* fygue_file_lseek(): seek directory */ extern off_t fygue_file_lseek( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, off_t offset, int whence ); /* fygue_file_write(): write directory (EROFS) */ extern ssize_t fygue_file_write( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, void *buffer, size_t size ); /* fygue_file_close(): close directory */ -extern int fygue_file_close(struct fygue_descriptor *desc); +extern int fygue_file_close( + struct fygue_fsinfo *fsinfo, + struct fygue_file *file +); /* fygue_file_sync(): file-specific sync */ -extern int fygue_file_sync(struct fygue_descriptor *desc); +extern int fygue_file_sync( + struct fygue_fsinfo *fsinfo, + struct fygue_file *file +); #ifdef __cplusplus } diff --git a/src/fs/fygue/fygue_dir_close.c b/src/fs/fygue/fygue_dir_close.c index a2e670f..ae5cdc0 100644 --- a/src/fs/fygue/fygue_dir_close.c +++ b/src/fs/fygue/fygue_dir_close.c @@ -1,31 +1,29 @@ #include #include +#include #include "fygue.h" #include "fat/fat.h" /* fygue_dir_close(): close directory */ -int fygue_dir_close(struct fygue_descriptor *desc) -{ - struct fygue_fsinfo *fsinfo; - - ENOTSUP_IF_NOT_FYGUE(-1); - if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { - errno = EBADF; - return -1; - } - if (fygue_descriptor_sync(&fsinfo, desc) != 0) { - errno = EIO; - return -1; - } - fygue_fat_dir_close(&(fsinfo->fat), &desc->resolve.dir.fat); - if (desc->resolve.dir.dirent != NULL) +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)); + if (dir->dirent != NULL) { - for (int i = 0 ; i < desc->resolve.dir.count ; i++) { - if (desc->resolve.dir.dirent[i] != NULL) - free(desc->resolve.dir.dirent[i]); + for (int i = 0 ; i < dir->count ; i++) { + if (dir->dirent[i] != NULL) + free(dir->dirent[i]); } - free(desc->resolve.dir.dirent); + free(dir->dirent); } - memset(desc, 0x00, sizeof(struct fygue_descriptor)); + if (dir->path != NULL) + free(dir->path); + memset(dir, 0x00, sizeof(struct fygue_dir)); return 0; } diff --git a/src/fs/fygue/fygue_dir_lseek.c b/src/fs/fygue/fygue_dir_lseek.c index f1809e1..d0d77f5 100644 --- a/src/fs/fygue/fygue_dir_lseek.c +++ b/src/fs/fygue/fygue_dir_lseek.c @@ -1,54 +1,24 @@ #include "fygue.h" -//--- -// Internals -//--- - -/* _fygue_dir_discover(): force discover all directory */ -static void _fygue_dir_discover(struct fygue_descriptor *desc) -{ - struct dirent *ent = NULL; - - while (true) - { - if (fygue_dir_read(desc, &ent, sizeof(ent)) != sizeof(ent)) - break; - } -} - -//--- -// Public -//--- - /* fygue_dir_lseek(): seek directory */ off_t fygue_dir_lseek( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, 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 (fygue_descriptor_sync(NULL, desc) != 0) { - errno = EIO; - return -1; - } + if (fsinfo == NULL || dir == NULL) + FYGUE_RET_ERRNO(EIO); + + if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) + FYGUE_RET_ERRNO(EINVAL); if(whence == SEEK_CUR) - offset += desc->resolve.dir.pos; - if(whence == SEEK_END) { - _fygue_dir_discover(desc); - offset += desc->resolve.dir.count; - } - if(offset < 0 || offset >= desc->resolve.dir.count + 1) { - errno = EINVAL; - return -1; - } - desc->resolve.dir.pos = offset; - return desc->resolve.dir.pos; + offset += dir->pos; + if(whence == SEEK_END) + offset += dir->count; + if(offset < 0 || offset >= dir->count + 1) + FYGUE_RET_ERRNO(EINVAL); + + dir->pos = offset; + return dir->pos; } diff --git a/src/fs/fygue/fygue_dir_open.c b/src/fs/fygue/fygue_dir_open.c new file mode 100644 index 0000000..cb222ee --- /dev/null +++ b/src/fs/fygue/fygue_dir_open.c @@ -0,0 +1,115 @@ +#include +#include +#include "fygue.h" + +//--- +// Internals +//--- + +/* realloc a prepare the internal table */ +static int _fygue_dir_open_table_realloc(struct fygue_dir *dir) +{ + void *tmp; + + tmp = reallocarray( + dir->dirent, + dir->dirent_idx_max + 16, + sizeof(struct dirent) + ); + if (tmp == NULL) + FYGUE_RET_ERRNO(ENOMEM); + dir->dirent = tmp; + dir->dirent_idx_max += 16; + for (int i = dir->count ; i < dir->dirent_idx_max ; i++) + dir->dirent[i] = NULL; + return 0; +} + +/* free internal table */ +static void _fygue_dir_open_table_free(struct fygue_dir *dir) +{ + if (dir->dirent == NULL) + return; + for (int i = 0 ; i < dir->dirent_idx_max ; i++) { + if (dir->dirent[i] != NULL) + free(dir->dirent[i]); + } + free(dir->dirent); + dir->dirent = NULL; +} + +/* convert FAT dirent to dirent */ +static int _fygue_dir_open_convert( + struct dirent **dirent, + struct fygue_fat_dirent *fat_dirent +) { + size_t len; + + len = strlen(fat_dirent->name); + *dirent = calloc(1, sizeof(struct dirent) + len + 2); + if (*dirent == NULL) + FYGUE_RET_ERRNO(ENOMEM); + (*dirent)->d_ino = fat_dirent->cluster_id; + (*dirent)->d_type = DT_REG; + memcpy((*dirent)->d_name, fat_dirent->name, len + 1); + return 0; +} + +/* _fygue_dir_open_discover(): discover all dirent */ +static int _fygue_dir_open_discover( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir +) { + struct fygue_fat_dirent dirent; + int rc; + + while (true) + { + rc = fygue_fat_dir_read(&(fsinfo->fat), &(dir->fat), &dirent); + if (rc == -1) + return 0; + if (rc < 0) + break; + if (dir->count >= dir->dirent_idx_max) { + if (_fygue_dir_open_table_realloc(dir) != 0) + break; + } + rc = _fygue_dir_open_convert(&(dir->dirent[dir->pos]), &dirent); + if (rc != 0) + break; + dir->count += 1; + } + _fygue_dir_open_table_free(dir); + FYGUE_RET_ERRNO(EIO); +} + +//--- +// Public +//--- + +/* fygue_dir_open(): directory-specific open */ +int fygue_dir_open( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, + char const * const path, + struct fygue_fat_dir *fat_dir +) { + if (fsinfo == NULL || dir == NULL || path == NULL || fat_dir == NULL) + return 1; + + memset(dir, 0x00, sizeof(struct fygue_dir)); + dir->path = strdup(path); + if (dir->path == NULL) + FYGUE_RET_ERRNO(ENOMEM); + dir->dirent_idx_max = 0; + dir->dirent = NULL; + dir->count = 0; + dir->pos = 0; + memcpy(&(dir->fat), fat_dir, sizeof(struct fygue_fat_dir)); + + if (_fygue_dir_open_discover(fsinfo, dir) != 0) { + free(dir->path); + return -1; + } + return 0; +} diff --git a/src/fs/fygue/fygue_dir_read.c b/src/fs/fygue/fygue_dir_read.c index 7ff183f..7683366 100644 --- a/src/fs/fygue/fygue_dir_read.c +++ b/src/fs/fygue/fygue_dir_read.c @@ -2,106 +2,25 @@ #include #include "fygue.h" -//--- -// Internals -//--- - -/* _fygue_dir_fat_read(): read and update internal cache - * - * return - * -2 no directory found - * -1 internal error - * 0 success */ -static int _fygue_dir_fat_read( - struct fygue_fsinfo *fsinfo, - struct fygue_descriptor *desc -) { - struct fygue_fat_dirent fat_dirent; - struct dirent **dirent; - void *tmp; - size_t len; - int rc; - - rc = fygue_fat_dir_read( - &(fsinfo->fat), - &(desc->resolve.dir.fat), - &fat_dirent - ); - if (rc <= -3) - return -2; - if (rc < 0) { - errno = EIO; - return -1; - } - tmp = reallocarray( - desc->resolve.dir.dirent, - desc->resolve.dir.count + 1, - sizeof(struct dirent *) - ); - if (tmp == NULL) { - errno = ENOMEM; - return -1; - } - desc->resolve.dir.dirent = tmp; - desc->resolve.dir.count += 1; - //FIXME: ensure UTF-8/SHIFT-JS - len = strlen(fat_dirent.name); - dirent = &(desc->resolve.dir.dirent[desc->resolve.dir.pos]); - *dirent = calloc(1, sizeof(struct dirent) + len + 2); - if (*dirent == NULL) { - desc->resolve.dir.count -= 1; - errno = ENOMEM; - return -1; - } - //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; -} - -//--- -// Public -//--- - /* fygue_dir_read(): directory read implementation * * notes * - assume that the directory have read permission */ -int fygue_dir_read( - struct fygue_descriptor *desc, +ssize_t fygue_dir_read( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, struct dirent **dirent, size_t size ) { - struct fygue_fsinfo *fsinfo; - 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_descriptor_sync(&fsinfo, desc) != 0) { - errno = EIO; - return -1; - } - if (desc->resolve.dir.pos >= desc->resolve.dir.count) - { - rc = _fygue_dir_fat_read(fsinfo, desc); - if (rc == -2) - return 0; - if (rc < 0) - return rc; - } - *dirent = desc->resolve.dir.dirent[desc->resolve.dir.pos]; - desc->resolve.dir.pos += 1; + if (fsinfo == NULL || dir == NULL) + FYGUE_RET_ERRNO(EIO); + if (dirent == NULL) + FYGUE_RET_ERRNO(EFAULT); + if (size < sizeof *dirent) + FYGUE_RET_ERRNO(EINVAL); + if (dir->pos >= dir->count) + FYGUE_RET_ERRNO(EIO); + *dirent = dir->dirent[dir->pos]; + dir->pos += 1; return sizeof *dirent; } diff --git a/src/fs/fygue/fygue_dir_sync.c b/src/fs/fygue/fygue_dir_sync.c index 7b5a296..215d7a9 100644 --- a/src/fs/fygue/fygue_dir_sync.c +++ b/src/fs/fygue/fygue_dir_sync.c @@ -1,33 +1,58 @@ #include +#include #include "fygue.h" /* fygue_dir_sync(): directory-specific sync */ -int fygue_dir_sync(struct fygue_descriptor *desc) -{ - struct fygue_fsinfo *fsinfo; +int fygue_dir_sync( + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir +) { + struct fygue_fat_descriptor desc; + int saved_pos; int rc; - ENOTSUP_IF_NOT_FYGUE(-1); - if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { - errno = EBADF; - return -1; - } - //if (desc->) - if (fygue_mount(&fsinfo, true)) { - errno = EIO; - return -1; - } - for (int i = 0 ; i < desc->resolve.dir.count ; i++) { - if (desc->resolve.dir.dirent[i] == NULL) - continue; - free(desc->resolve.dir.dirent[i]); - desc->resolve.dir.dirent[i] = NULL; - } + /* preliminary check */ + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); + if (fsinfo == NULL || dir == NULL) + FYGUE_RET_ERRNO(EIO); + + /* update FAT-specific information */ + //TODO: assume that the first cluster will remain the same ? + if (fygue_fat_open(&(fsinfo->fat), dir->path, &desc) != 0) + FYGUE_RET_ERRNO(ENOENT); + if (desc.type != FYGUE_FAT_DESC_TYPE_FILE) + FYGUE_RET_ERRNO(EIO); rc = fygue_fat_dir_sync( &(fsinfo->fat), - &(desc->resolve.dir.fat) + &(desc.dir), + desc.file.cluster_entry ); if (rc != 0) - return -2; + FYGUE_RET_ERRNO(EIO); + + /* refresh internal information */ + //TODO: re-use realloc + if (dir->dirent != NULL) + { + for (int i = 0 ; i < dir->count ; i++) + { + if (dir->dirent[i] == NULL) + continue; + free(dir->dirent[i]); + dir->dirent[i] = NULL; + } + free(dir->dirent); + dir->dirent = NULL; + dir->count = 0; + } + /* hack to force regenerate the dirent cache */ + saved_pos = dir->pos; + if ( + fygue_dir_lseek(fsinfo, dir, 0, SEEK_SET) != 0 || + fygue_dir_lseek(fsinfo, dir, saved_pos, SEEK_SET) != 0 + ) { + return -1; + } return 0; } diff --git a/src/fs/fygue/fygue_dir_write.c b/src/fs/fygue/fygue_dir_write.c index 5fba95d..7bcb5d2 100644 --- a/src/fs/fygue/fygue_dir_write.c +++ b/src/fs/fygue/fygue_dir_write.c @@ -2,21 +2,16 @@ /* fygue_dir_write(): write directory (EISDIR) */ ssize_t fygue_dir_write( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_dir *dir, void *buffer, size_t size ) { - ENOTSUP_IF_NOT_FYGUE(-1); - if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { - errno = EBADF; - return -1; - } - if (buffer == NULL) { - errno = EFAULT; - return -1; - } - if (size == 0) - return 0; - errno = EISDIR; - return -1; + if (fsinfo == NULL || dir == NULL) + FYGUE_RET_ERRNO(EIO); + if (buffer == NULL) + FYGUE_RET_ERRNO(EFAULT); + if (size != 0) + FYGUE_RET_ERRNO(EISDIR); + return 0; } diff --git a/src/fs/fygue/fygue_file_close.c b/src/fs/fygue/fygue_file_close.c index 51131c2..936a482 100644 --- a/src/fs/fygue/fygue_file_close.c +++ b/src/fs/fygue/fygue_file_close.c @@ -1,23 +1,15 @@ #include -#include #include "fygue.h" #include "fat/fat.h" /* fygue_file_close(): close directory */ -int fygue_file_close(struct fygue_descriptor *desc) -{ - struct fygue_fsinfo *fsinfo; - - ENOTSUP_IF_NOT_FYGUE(-1); - if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { - errno = EBADF; - return -1; - } - if (fygue_descriptor_sync(&fsinfo, desc) != 0) { - errno = EIO; - return -1; - } - fygue_fat_file_close(&(fsinfo->fat), &desc->resolve.file.fat); - memset(desc, 0x00, sizeof(struct fygue_descriptor)); +int fygue_file_close( + struct fygue_fsinfo *fsinfo, + struct fygue_file *file +) { + if (fsinfo == NULL || file == NULL) + FYGUE_RET_ERRNO(EIO); + fygue_fat_file_close(&(fsinfo->fat), &(file->fat)); + free(file); return 0; } diff --git a/src/fs/fygue/fygue_file_lseek.c b/src/fs/fygue/fygue_file_lseek.c index e4ff525..ff8fa8c 100644 --- a/src/fs/fygue/fygue_file_lseek.c +++ b/src/fs/fygue/fygue_file_lseek.c @@ -2,38 +2,26 @@ /* fygue_file_lseek(): seek file */ off_t fygue_file_lseek( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, off_t offset, int whence ) { - struct fygue_fsinfo *fsinfo; + if (fsinfo == NULL || file == NULL) + FYGUE_RET_ERRNO(EIO); + if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) + FYGUE_RET_ERRNO(EINVAL); - 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 (fygue_descriptor_sync(&fsinfo, desc) != 0) { - errno = EIO; - return -1; - } if(whence == SEEK_CUR) - offset += desc->resolve.dir.pos; + offset += file->cursor; 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; - fygue_fat_file_seek( - &(fsinfo->fat), - &(desc->resolve.file.fat), - offset - ); - return desc->resolve.file.cursor; + offset += file->size; + if(offset < 0 || (unsigned)offset >= file->size + 1) + FYGUE_RET_ERRNO(EINVAL); + + if (fygue_fat_file_seek(&(fsinfo->fat), &(file->fat), offset) != 0) + FYGUE_RET_ERRNO(EIO); + + file->cursor = offset; + return file->cursor; } diff --git a/src/fs/fygue/fygue_file_open.c b/src/fs/fygue/fygue_file_open.c new file mode 100644 index 0000000..5f9d59e --- /dev/null +++ b/src/fs/fygue/fygue_file_open.c @@ -0,0 +1,21 @@ +#include +#include "fygue.h" + +/* fygue_file_open(): file open */ +int fygue_file_open( + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, + char const * const path, + struct fygue_fat_file *fat_file +) { + if (fsinfo == NULL || file == NULL || path == NULL || fat_file == NULL) + return -1; + + memset(file, 0x00, sizeof(struct fygue_file)); + file->path = strdup(path); + if (file->path == NULL) + FYGUE_RET_ERRNO(ENOMEM); + file->cursor = 0; + 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 1f8c18f..8f6b38c 100644 --- a/src/fs/fygue/fygue_file_read.c +++ b/src/fs/fygue/fygue_file_read.c @@ -1,35 +1,19 @@ -#include -#include #include "fygue.h" -/* fygue_file_read(): write directory (EISDIR) */ +/* fygue_file_read(): read file data */ ssize_t fygue_file_read( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, 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_file_sync(desc) != 0) { - errno = EIO; - return -1; - } - if (fygue_mount(&fsinfo, true) != 0) { - errno = EIO; - return -1; - } + if (fsinfo == NULL || file == NULL) + FYGUE_RET_ERRNO(EIO); + if (buffer == NULL) + FYGUE_RET_ERRNO(EFAULT); return fygue_fat_file_read( &(fsinfo->fat), - &(desc->resolve.file.fat), + &(file->fat), buffer, size ); diff --git a/src/fs/fygue/fygue_file_sync.c b/src/fs/fygue/fygue_file_sync.c index 52d10a2..fd3f65e 100644 --- a/src/fs/fygue/fygue_file_sync.c +++ b/src/fs/fygue/fygue_file_sync.c @@ -1,26 +1,30 @@ +#include #include "fygue.h" /* fygue_file_sync(): file-specific sync */ -int fygue_file_sync(struct fygue_descriptor *desc) -{ - struct fygue_fsinfo *fsinfo; +int fygue_file_sync( + struct fygue_fsinfo *fsinfo, + struct fygue_file *file +) { + struct fygue_fat_descriptor desc; int rc; - ENOTSUP_IF_NOT_FYGUE(-1); - if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { - errno = EBADF; - return -1; - } - if (fygue_mount(&fsinfo, true)) { - errno = EIO; - return -1; - } - // nothing to sync in high-level + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); + if (fsinfo == NULL || file == NULL) + FYGUE_RET_ERRNO(EIO); + + //TODO: assume that the first cluster will remain the same ? + if (fygue_fat_open(&(fsinfo->fat), file->path, &desc) != 0) + FYGUE_RET_ERRNO(ENOENT); + if (desc.type != FYGUE_FAT_DESC_TYPE_FILE) + FYGUE_RET_ERRNO(EIO); rc = fygue_fat_file_sync( &(fsinfo->fat), - &(desc->resolve.file.fat) + &(desc.file), + desc.file.cluster_entry ); if (rc != 0) - return -1; + FYGUE_RET_ERRNO(EIO); return 0; } diff --git a/src/fs/fygue/fygue_file_write.c b/src/fs/fygue/fygue_file_write.c index c694d8f..5e6555a 100644 --- a/src/fs/fygue/fygue_file_write.c +++ b/src/fs/fygue/fygue_file_write.c @@ -2,21 +2,16 @@ /* fygue_file_write(): write directory (EISDIR) */ ssize_t fygue_file_write( - struct fygue_descriptor *desc, + struct fygue_fsinfo *fsinfo, + struct fygue_file *file, 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; + if (fsinfo == NULL || file == NULL) + FYGUE_RET_ERRNO(EIO); + if (buffer == NULL) + FYGUE_RET_ERRNO(EFAULT); + if (size != 0) + FYGUE_RET_ERRNO(EROFS); + return 0; } diff --git a/src/fs/fygue/fygue_mount.c b/src/fs/fygue/fygue_mount.c new file mode 100644 index 0000000..e28af96 --- /dev/null +++ b/src/fs/fygue/fygue_mount.c @@ -0,0 +1,45 @@ +#include +#include "fygue.h" + +//--- +// Internals +//--- + +/* __fygue_fsinfo: internal filesystem information */ +static struct fygue_fsinfo *__fygue_fsinfo = NULL; + +//--- +// Public +//--- + +/* fygue_mount() - mount (if needed) and return the filesystem information + * + * notes + * - assume that this global is const after initialisation */ +int fygue_mount(struct fygue_fsinfo **fsinfo) +{ + if (fsinfo == NULL) + return -1; + *fsinfo = NULL; + if (__fygue_fsinfo == NULL) + { + __fygue_fsinfo = calloc(1, sizeof(struct fygue_fsinfo)); + if (__fygue_fsinfo == NULL) + return -2; + if (fygue_fat_initialize(&(__fygue_fsinfo->fat)) != 0) + { + free(__fygue_fsinfo); + __fygue_fsinfo = NULL; + return -3; + } + __fygue_fsinfo->dirty = false; + } + if (__fygue_fsinfo->dirty) + { + if (fygue_fat_sync(&(__fygue_fsinfo->fat)) != 0) + return -4; + __fygue_fsinfo->dirty = false; + } + *fsinfo = __fygue_fsinfo; + return 0; +} diff --git a/src/fs/fygue/fygue_open.c b/src/fs/fygue/fygue_open.c index 2f95b86..dfc90fb 100644 --- a/src/fs/fygue/fygue_open.c +++ b/src/fs/fygue/fygue_open.c @@ -2,65 +2,86 @@ #include #include #include +#include #include "../fugue/fugue.h" #include "fygue.h" +//--- +// Public +//--- + +/* fygue_open_resolve() - try to resolve path + * + * notes + * - assume that path is clean + * - automatically mount the filesystem if needed + * - the saved pathname will not be saved in stat */ +int fygue_open_resolve( + char const * const path, + struct fygue_descriptor *desc +) { + struct fygue_fat_descriptor fat_desc; + struct fygue_fsinfo *fsinfo; + + if (path == NULL || path[0] != '/' || desc == NULL) + return -1; + if (fygue_mount(&fsinfo) != 0) + return -2; + if (fygue_fat_open(&(fsinfo->fat), path, &fat_desc) != 0) + return -3; + memset(desc, 0x00, sizeof(struct fygue_descriptor)); + if (fat_desc.type == FYGUE_FAT_DESC_TYPE_DIR) + { + desc->type = FYGUE_DESC_TYPE_DIR; + return fygue_dir_open(fsinfo, &(desc->dir), path, &(fat_desc.dir)); + } + desc->type = FYGUE_DESC_TYPE_FILE; + return fygue_file_open(fsinfo, &(desc->file), path, &fat_desc.file); +} + /* fygue_open(): open primitive */ int fygue_open(char const *path, int flags, GUNUSED mode_t mode) { - struct fygue_descriptor *desc; - struct fygue_resolve resolve; - fs_descriptor_t data; + struct fygue_descriptor desc; + fs_descriptor_t gint_desc; + int exists; - if ((flags & O_RDWR) || (flags & O_WRONLY)) { - errno = EROFS; - return -1; - } - ENOTSUP_IF_NOT_FYGUE(-1); + /* preliminary checks */ + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); + if ((flags & O_RDWR) || (flags & O_WRONLY)) + FYGUE_RET_ERRNO(EROFS); /* resolve the entry */ - int exists = fygue_resolve(path, &resolve); + exists = fygue_open_resolve(path, &desc); /* if opening fails and no explicit file creation is required, fail */ - if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY)))) { - errno = ENOENT; - return -1; - } - + if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY)))) + FYGUE_RET_ERRNO(ENOENT); /* if opening fails and the previous check as not returned an error, * it is certainly because of a creation request. We are a read-only * file-system, so, fail */ - if (exists < 0) { - errno = EROFS; - return -1; - } + if (exists < 0) + FYGUE_RET_ERRNO(EROFS); /* If the entry exists and O_EXCL was requested, fail. * note that Exclusive open means no sense unless creation is also * requested */ - if(exists >= 0 && (flags & O_EXCL)) { - errno = EEXIST; - return -1; - } + if(exists >= 0 && (flags & O_EXCL)) + FYGUE_RET_ERRNO(EEXIST); /* generate the final file descriptor */ - desc = calloc(1, sizeof(struct fygue_descriptor)); - if (desc == NULL) { - errno = ENOMEM; - return -1; + gint_desc.type = &fygue_file_descriptor_type; + gint_desc.data = calloc(1, sizeof(struct fygue_descriptor)); + if (gint_desc.data == NULL) + FYGUE_RET_ERRNO(ENOMEM); + memcpy(gint_desc.data, &desc, sizeof(struct fygue_descriptor)); + if (flags & O_DIRECTORY) + { + if (desc.type != FYGUE_DESC_TYPE_DIR) + FYGUE_RET_ERRNO(ENOTDIR); + gint_desc.type = &fygue_dir_descriptor_type; } - desc->path = strdup(path); - desc->flags = flags; - memcpy(&(desc->resolve), &resolve, sizeof(struct fygue_resolve)); - data.type = &fygue_descriptor_type; - data.data = desc; - if (flags & O_DIRECTORY) { - if (resolve.type != FYGUE_FILE_TYPE_DIR) { - errno = ENOTDIR; - return -1; - } - data.type = &fygue_dir_descriptor_type; - } - return fs_create_descriptor(&data); + return fs_create_descriptor(&gint_desc); } diff --git a/src/fs/fygue/fygue_stat.c b/src/fs/fygue/fygue_stat.c index 97f867c..5ed9de7 100644 --- a/src/fs/fygue/fygue_stat.c +++ b/src/fs/fygue/fygue_stat.c @@ -1,35 +1,22 @@ +#include #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_descriptor desc; 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 - ); + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); + if (path == NULL || statbuf == NULL) + FYGUE_RET_ERRNO(EFAULT); + if (fygue_mount(&fsinfo) != 0) + FYGUE_RET_ERRNO(EIO); + if (fygue_open_resolve(path, &desc) != 0) + FYGUE_RET_ERRNO(ENOENT); + if (desc.type == FYGUE_DESC_TYPE_DIR) + return fygue_fat_dir_stat(&(fsinfo->fat), &(desc.dir.fat), statbuf); + return fygue_fat_file_stat(&(fsinfo->fat), &(desc.file.fat), statbuf); } diff --git a/src/fs/fygue/fygue_syncfs.c b/src/fs/fygue/fygue_syncfs.c index a6403c3..d741925 100644 --- a/src/fs/fygue/fygue_syncfs.c +++ b/src/fs/fygue/fygue_syncfs.c @@ -1,16 +1,20 @@ +#include #include "fygue.h" +/* fygue_syncfs() - request filesystem re-synchronisation */ int fygue_syncfs(void *data) { struct fygue_fsinfo *fsinfo; - struct fygue_descriptor *descriptor; + struct fygue_descriptor *desc; + if(gint[HWFS] != HWFS_FUGUE) + FYGUE_RET_ERRNO(ENOTSUP); if (data == NULL) - return -1; - if (fygue_mount(&fsinfo, false) != 0) - return -2; - descriptor = data; - descriptor->dirty = true; + FYGUE_RET_ERRNO(EBADF); + if (fygue_mount(&fsinfo) != 0) + FYGUE_RET_ERRNO(EIO); + desc = data; + desc->dirty = true; fsinfo->dirty = true; return 0; }