fygue: (untested) complete re-architecture + syncfs() support

This commit is contained in:
Yann MAGNIN 2025-04-10 13:15:04 +02:00
parent c99a18d748
commit 69d59cd4d2
No known key found for this signature in database
GPG key ID: D82629D933EADC59
32 changed files with 753 additions and 600 deletions

View file

@ -264,31 +264,38 @@ set(SOURCES
src/fs/fygue/fygue_open.c src/fs/fygue/fygue_open.c
src/fs/fygue/fygue_syncfs.c src/fs/fygue/fygue_syncfs.c
src/fs/fygue/fygue_stat.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_read.c
src/fs/fygue/fygue_dir_lseek.c
src/fs/fygue/fygue_dir_write.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_dir_close.c
src/fs/fygue/fygue_file_lseek.c src/fs/fygue/fygue_dir_sync.c
src/fs/fygue/fygue_file_write.c src/fs/fygue/fygue_file_open.c
src/fs/fygue/fygue_file_close.c
src/fs/fygue/fygue_file_read.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/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_open.c
src/fs/fygue/fat/fat_dir_read.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_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_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_read.c
src/fs/fygue/fat/fat_file_seek.c src/fs/fygue/fat/fat_file_seek.c
src/fs/fygue/fat/resolve.c src/fs/fygue/fat/fat_file_stat.c
src/fs/fygue/fat/sector.c src/fs/fygue/fat/fat_file_close.c
src/fs/fygue/flash/cluster.c src/fs/fygue/fat/fat_file_sync.c
src/fs/fygue/flash/cmap.c src/fs/fygue/fat/fat_open.c
src/fs/fygue/flash/flash.c src/fs/fygue/fat/flash/cluster.c
src/fs/fygue/flash/sector.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) set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png)

View file

@ -60,7 +60,7 @@ bool fs_descriptor_is_fygue(fs_descriptor_t const *desc)
{ {
return ( return (
(desc->type == &fygue_dir_descriptor_type) || (desc->type == &fygue_dir_descriptor_type) ||
(desc->type == &fygue_descriptor_type) (desc->type == &fygue_file_descriptor_type)
); );
} }

View file

@ -2,7 +2,7 @@
** fygue/fat/cluster - FAT cluster handling ** fygue/fat/cluster - FAT cluster handling
*/ */
#include "fat.h" #include "fat.h"
#include "../flash/flash.h" #include "flash/flash.h"
//--- //---
// Internals // Internals

View file

@ -4,14 +4,14 @@
#include <gint/defs/types.h> #include <gint/defs/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "../flash/flash.h" #include "flash/flash.h"
/* _FAT_WORD() : helper for 16bit value */ /* _FAT_WORD() : helper for 16bit value */
#define FAT_WORD(x) \ #define FAT_WORD(x) \
(((x & 0xff00) >> 8) | ((x & 0x00ff) << 8)) (((x & 0xff00) >> 8) | ((x & 0x00ff) << 8))
/* _FAT_DWORD() : helper for 32bit value */ /* _FAT_DWORD() : helper for 32bit value */
#define FAT_DWORD(x) ( \ #define FAT_DWORD(x) ( \
(((x) & 0xff000000) >> 24) \ (((x) & 0xff000000) >> 24) \
| (((x) & 0x00ff0000) >> 8) \ | (((x) & 0x00ff0000) >> 8) \
| (((x) & 0x0000ff00) << 8) \ | (((x) & 0x0000ff00) << 8) \
@ -94,12 +94,12 @@ struct fygue_fat_file
int chunk_rd_offset; int chunk_rd_offset;
}; };
/* fygue_fat_resolve: internal resolve information */ /* fygue_fat_descriptor: FAT descriptor information */
struct fygue_fat_resolve struct fygue_fat_descriptor
{ {
enum { enum {
FYGUE_FAT_FILE_TYPE_FILE, FYGUE_FAT_DESC_TYPE_FILE,
FYGUE_FAT_FILE_TYPE_DIR, FYGUE_FAT_DESC_TYPE_DIR,
} type; } type;
union { union {
struct fygue_fat_file file; struct fygue_fat_file file;
@ -107,17 +107,21 @@ struct fygue_fat_resolve
}; };
}; };
//---
// Public interface
//---
/* fygue_fat_initialize() - fully initialize the FAT information */ /* fygue_fat_initialize() - fully initialize the FAT information */
extern int fygue_fat_initialize(struct fygue_fat *fat); extern int fygue_fat_initialize(struct fygue_fat *fat);
/* fygue_fat_sync() - re-initialize the FAT information */ /* fygue_fat_sync() - re-initialize the FAT information */
extern int fygue_fat_sync(struct fygue_fat *fat); extern int fygue_fat_sync(struct fygue_fat *fat);
/* fygue_fat_resolve() - resolve the path and set the dirent information */ /* fygue_fat_open() - resolve the path and set the dirent information */
extern int fygue_fat_resolve( extern int fygue_fat_open(
struct fygue_fat *fat, struct fygue_fat *fat,
char const * const path, 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 */ /* fygue_fat_dir_sync(): sync directory information */
extern int fygue_fat_dir_sync( extern int fygue_fat_dir_sync(
struct fygue_fat *fat, 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 */ /* fygue_fat_file_sync(): sync internal information */
extern int fygue_fat_file_sync( extern int fygue_fat_file_sync(
struct fygue_fat *fat, struct fygue_fat *fat,
struct fygue_fat_file *file struct fygue_fat_file *file,
int cluster_id
); );
//--- //---

View file

@ -7,38 +7,17 @@ int fygue_fat_dir_open(
struct fygue_fat_dir *dir, struct fygue_fat_dir *dir,
struct fygue_fat_dirent *dirent struct fygue_fat_dirent *dirent
) { ) {
int rc;
memset(dir, 0x00, sizeof(struct fygue_fat_dir)); memset(dir, 0x00, sizeof(struct fygue_fat_dir));
if (dirent == NULL) { if (dirent == NULL) {
dir->cluster_entry = 0; dir->cluster_entry = 0;
dir->root_dirent_count = fat->RootEntCount; dir->root_dirent_count = fat->RootEntCount;
dir->attribute = FYGUE_FAT_FILE_TYPE_DIR; dir->attribute = FYGUE_FAT_DESC_TYPE_DIR;
} else { } else {
if ((dirent->attribute & FYGUE_FAT_FILE_TYPE_DIR) == 0x00) if ((dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY) == 0x00)
return -1; return -1;
dir->cluster_entry = dirent->cluster_id; 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->root_dirent_count = 0;
} }
dir->dirty = false; return fygue_fat_dir_sync(fat, dir, dir->cluster_entry);
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;
} }

View file

@ -3,10 +3,32 @@
/* fygue_fat_dir_sync(): sync directory information */ /* fygue_fat_dir_sync(): sync directory information */
int fygue_fat_dir_sync( int fygue_fat_dir_sync(
struct fygue_fat *fat, struct fygue_fat *fat,
struct fygue_fat_dir *dir struct fygue_fat_dir *dir,
int cluster_id
) { ) {
int rc;
if (fat == NULL || dir == NULL) if (fat == NULL || dir == NULL)
return -1; 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; return 0;
} }

View file

@ -15,7 +15,7 @@ int fygue_fat_file_open(
file->chunk = NULL; file->chunk = NULL;
file->chunk_count = 0; file->chunk_count = 0;
file->chunk_table_max_index = 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; return -1;
if (fygue_fat_file_seek(fat, file, 0) != 0) if (fygue_fat_file_seek(fat, file, 0) != 0)
return -2; return -2;

View file

@ -60,15 +60,15 @@ static int _fygue_chunk_error(struct fygue_fat_file *file)
/* fygue_fat_file_sync(): sync internal information */ /* fygue_fat_file_sync(): sync internal information */
int fygue_fat_file_sync( int fygue_fat_file_sync(
struct fygue_fat *fat, struct fygue_fat *fat,
struct fygue_fat_file *file struct fygue_fat_file *file,
int cluster_id
) { ) {
uintptr_t cluster_addr; uintptr_t cluster_addr;
int cluster_id;
if (fat == NULL || file == NULL) if (fat == NULL || file == NULL)
return -1; return -1;
file->chunk_count = 0; file->chunk_count = 0;
cluster_id = file->cluster_entry; file->cluster_entry = cluster_id;
while (true) while (true)
{ {
if (fygue_fat_cluster_get_addr(fat, &cluster_addr, cluster_id) != 0) if (fygue_fat_cluster_get_addr(fat, &cluster_addr, cluster_id) != 0)

View file

@ -52,15 +52,16 @@ static int _fygue_dirent_find(
/* _fygue_resolve_set(): setup the resolve response */ /* _fygue_resolve_set(): setup the resolve response */
static int _fygue_resolve_set( static int _fygue_resolve_set(
struct fygue_fat *fat, struct fygue_fat *fat,
struct fygue_fat_resolve *resolve, struct fygue_fat_descriptor *desc,
struct fygue_fat_dirent *dirent struct fygue_fat_dirent *dirent
) { ) {
if (dirent == NULL || (dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY)) { if (dirent == NULL || (dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY)) {
resolve->type = FYGUE_FAT_FILE_TYPE_DIR; desc->type = FYGUE_FAT_DESC_TYPE_DIR;
return fygue_fat_dir_open(fat, &(resolve->dir), dirent); 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 * notes
* - assume that the path is clean */ * - assume that the path is clean */
int fygue_fat_resolve( int fygue_fat_open(
struct fygue_fat *fat, struct fygue_fat *fat,
char const * const path, char const * const path,
struct fygue_fat_resolve *resolve struct fygue_fat_descriptor *desc
) { ) {
struct fygue_fat_dirent dirent; struct fygue_fat_dirent dirent;
struct fygue_fat_dir dir; struct fygue_fat_dir dir;
@ -83,7 +84,7 @@ int fygue_fat_resolve(
size_t len; size_t len;
bool is_root; bool is_root;
if (fat == NULL || path == NULL || resolve == NULL) if (fat == NULL || path == NULL || desc == NULL)
return -1; return -1;
if (path[0] != '/') if (path[0] != '/')
return -1; return -1;
@ -107,6 +108,6 @@ int fygue_fat_resolve(
return -5; return -5;
} }
if (is_root) if (is_root)
return _fygue_resolve_set(fat, resolve, NULL); return _fygue_resolve_set(fat, desc, NULL);
return _fygue_resolve_set(fat, resolve, &dirent); return _fygue_resolve_set(fat, desc, &dirent);
} }

View file

@ -1,129 +1,171 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <gint/hardware.h>
#include "fygue.h" #include "fygue.h"
//--- //---
// Internals // Internals
//--- //---
/* __fygue_fsinfo: internal filesystem information */ /* FYGUE_GFDI_CHEK - shorthand for all GFDI prologue */
static struct fygue_fsinfo *__fygue_fsinfo = NULL; #define FYGUE_GFDI_CHEK(type) \
_fygue_gfdi_ensure_valid(&fsinfo, desc, type)
//--- /* _fygue_gfdi_ensure_valid(): ensure GFDI validity
// Primitives
//---
/* fygue_mount() - mount (if needed) and return the filesystem information
* *
* notes * notes:
* - assume that this global is const after initialisation */ * - assume info is not NULL
int fygue_mount(struct fygue_fsinfo **fsinfo, bool refresh) * - auto mount the FS (if needed) and get information
{ * - ensure file sync if needed */
if (fsinfo == NULL) static int _fygue_gfdi_ensure_valid(
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(
struct fygue_fsinfo **fsinfo, struct fygue_fsinfo **fsinfo,
struct fygue_descriptor *desc struct fygue_descriptor *desc,
unsigned int type
) { ) {
int (*sync)(struct fygue_descriptor*); int rc;
struct fygue_fsinfo *ffsinfo;
if (fygue_mount(&ffsinfo, true) != 0) if(gint[HWFS] != HWFS_FUGUE)
return -2; FYGUE_RET_ERRNO(ENOTSUP);
if (fsinfo != NULL) if (fsinfo == NULL)
*fsinfo = ffsinfo; FYGUE_RET_ERRNO(EIO);
if (desc != NULL && desc->dirty) 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->type == FYGUE_DESC_TYPE_DIR)
if (desc->resolve.type == FYGUE_FILE_TYPE_DIR) rc = fygue_dir_sync(*fsinfo, &(desc->dir));
sync = &fygue_dir_sync; if (desc->type == FYGUE_DESC_TYPE_FILE)
if (sync(desc) != 0) rc = fygue_file_sync(*fsinfo, &(desc->file));
return -1; if (rc != 0)
FYGUE_RET_ERRNO(EIO);
desc->dirty = false; desc->dirty = false;
} }
return 0; 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 // Descriptor
//--- //---
const fs_descriptor_type_t fygue_descriptor_type = { /* fygue_file_descriptor_type - fygue file descriptor */
.read = (void*)&fygue_file_read, const fs_descriptor_type_t fygue_file_descriptor_type = {
.write = (void*)&fygue_file_write, .read = (void*)&fygue_gfdi_file_read,
.lseek = (void*)&fygue_file_lseek, .write = (void*)&fygue_gfdi_file_write,
.close = (void*)&fygue_file_close, .lseek = (void*)&fygue_gfdi_file_lseek,
.close = (void*)&fygue_gfdi_file_close,
}; };
const fs_descriptor_type_t fygue_dir_descriptor_type = { const fs_descriptor_type_t fygue_dir_descriptor_type = {
.read = (void*)&fygue_dir_read, .read = (void*)&fygue_gfdi_dir_read,
.write = (void*)&fygue_dir_write, .write = (void*)&fygue_gfdi_dir_write,
.lseek = (void*)&fygue_dir_lseek, .lseek = (void*)&fygue_gfdi_dir_lseek,
.close = (void*)&fygue_dir_close, .close = (void*)&fygue_gfdi_dir_close,
}; };

View file

@ -10,13 +10,15 @@ extern "C" {
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <gint/fs.h> #include <gint/fs.h>
#include <errno.h>
#include "fat/fat.h"
//--- //---
// Public global // Public global
//--- //---
/* File descriptor type */ /* 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 */ /* Directory descriptor type */
extern const fs_descriptor_type_t fygue_dir_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 // Public (low-level) API
//--- //---
/* fygue_open() - open file or directory */ /* helper to set errno and return -1 */
extern int fygue_open(char const *path, int flags, mode_t mode); #define FYGUE_RET_ERRNO(error) \
do { errno = error; return -1; } while(0);
/* 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 <gint/hardware.h>
#include <errno.h>
#define ENOTSUP_IF_NOT_FYGUE(rc) \
if(gint[HWFS] != HWFS_FUGUE) { \
errno = ENOTSUP; \
return (rc); \
}
#include "fat/fat.h"
/* fygue_fsinfo: internal fygue FS information */ /* fygue_fsinfo: internal fygue FS information */
struct fygue_fsinfo struct fygue_fsinfo
@ -55,111 +37,162 @@ struct fygue_fsinfo
bool dirty; bool dirty;
}; };
/* fygue_resolve: internals file information */ /* fygue_open() - open file or directory */
struct fygue_resolve { extern int fygue_open(char const *path, int flags, mode_t mode);
enum {
FYGUE_FILE_TYPE_FILE,
FYGUE_FILE_TYPE_DIR, /* fygue_stat() - get file or directory information */
} type; extern int fygue_stat(char const *path, struct stat *statbuf);
union {
struct { /* fygue_syncfs() - request filesystem re-synchronisation */
off_t cursor; extern int fygue_syncfs(void *data);
struct fygue_fat_file fat;
} file; /* fygue_mount() - mount the filesystem */
struct { extern int fygue_mount(struct fygue_fsinfo **fsinfo);
struct fygue_fat_dir fat;
struct dirent **dirent; //---
int count; // Internals
int pos; //---
} dir;
}; /* 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_descriptor
{ {
struct fygue_resolve resolve; enum {
char const *path; FYGUE_DESC_TYPE_FILE,
int flags; FYGUE_DESC_TYPE_DIR,
} type;
union {
struct fygue_file file;
struct fygue_dir dir;
};
bool dirty; 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 */ /* fygue_open_resolve() - open file or directory */
extern int fygue_descriptor_sync( extern int fygue_open_resolve(
struct fygue_fsinfo **fsinfo, char const *path,
struct fygue_descriptor *desc struct fygue_descriptor *desc
); );
/* fygue_resolve() - try to resolve path */
extern int fygue_resolve(
char const * const path,
struct fygue_resolve *resolve
);
//--- //---
// Directory interface // 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 */ /* fygue_dir_read(): directory read implementation */
extern int fygue_dir_read( extern ssize_t fygue_dir_read(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_dir *dir,
struct dirent **dirent, struct dirent **dirent,
size_t size size_t size
); );
/* fygue_dir_lseek(): seek directory */ /* fygue_dir_lseek(): seek directory */
extern off_t fygue_dir_lseek( extern off_t fygue_dir_lseek(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_dir *dir,
off_t offset, off_t offset,
int whence int whence
); );
/* fygue_dir_write(): write directory (EISDIR) */ /* fygue_dir_write(): write directory (EISDIR) */
extern ssize_t fygue_dir_write( extern ssize_t fygue_dir_write(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_dir *dir,
void *buffer, void *buffer,
size_t size size_t size
); );
/* fygue_dir_close(): close directory */ /* 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 */ /* 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 // 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 */ /* fygue_file_read(): read primitive */
extern ssize_t fygue_file_read( extern ssize_t fygue_file_read(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_file *file,
void *buffer, void *buffer,
size_t size size_t size
); );
/* fygue_file_lseek(): seek directory */ /* fygue_file_lseek(): seek directory */
extern off_t fygue_file_lseek( extern off_t fygue_file_lseek(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_file *file,
off_t offset, off_t offset,
int whence int whence
); );
/* fygue_file_write(): write directory (EROFS) */ /* fygue_file_write(): write directory (EROFS) */
extern ssize_t fygue_file_write( extern ssize_t fygue_file_write(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_file *file,
void *buffer, void *buffer,
size_t size size_t size
); );
/* fygue_file_close(): close directory */ /* 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 */ /* 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 #ifdef __cplusplus
} }

View file

@ -1,31 +1,29 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <gint/hardware.h>
#include "fygue.h" #include "fygue.h"
#include "fat/fat.h" #include "fat/fat.h"
/* fygue_dir_close(): close directory */ /* fygue_dir_close(): close directory */
int fygue_dir_close(struct fygue_descriptor *desc) int fygue_dir_close(
{ struct fygue_fsinfo *fsinfo,
struct fygue_fsinfo *fsinfo; struct fygue_dir *dir
) {
ENOTSUP_IF_NOT_FYGUE(-1); if(gint[HWFS] != HWFS_FUGUE)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { FYGUE_RET_ERRNO(ENOTSUP);
errno = EBADF; if (fsinfo == NULL || dir == NULL)
return -1; FYGUE_RET_ERRNO(EIO);
} fygue_fat_dir_close(&(fsinfo->fat), &(dir->fat));
if (fygue_descriptor_sync(&fsinfo, desc) != 0) { if (dir->dirent != NULL)
errno = EIO;
return -1;
}
fygue_fat_dir_close(&(fsinfo->fat), &desc->resolve.dir.fat);
if (desc->resolve.dir.dirent != NULL)
{ {
for (int i = 0 ; i < desc->resolve.dir.count ; i++) { for (int i = 0 ; i < dir->count ; i++) {
if (desc->resolve.dir.dirent[i] != NULL) if (dir->dirent[i] != NULL)
free(desc->resolve.dir.dirent[i]); 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; return 0;
} }

View file

@ -1,54 +1,24 @@
#include "fygue.h" #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 */ /* fygue_dir_lseek(): seek directory */
off_t fygue_dir_lseek( off_t fygue_dir_lseek(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_dir *dir,
off_t offset, off_t offset,
int whence int whence
) { ) {
ENOTSUP_IF_NOT_FYGUE(-1); if (fsinfo == NULL || dir == NULL)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { FYGUE_RET_ERRNO(EIO);
errno = EBADF;
return -1; if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END)
} FYGUE_RET_ERRNO(EINVAL);
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(whence == SEEK_CUR) if(whence == SEEK_CUR)
offset += desc->resolve.dir.pos; offset += dir->pos;
if(whence == SEEK_END) { if(whence == SEEK_END)
_fygue_dir_discover(desc); offset += dir->count;
offset += desc->resolve.dir.count; if(offset < 0 || offset >= dir->count + 1)
} FYGUE_RET_ERRNO(EINVAL);
if(offset < 0 || offset >= desc->resolve.dir.count + 1) {
errno = EINVAL; dir->pos = offset;
return -1; return dir->pos;
}
desc->resolve.dir.pos = offset;
return desc->resolve.dir.pos;
} }

View file

@ -0,0 +1,115 @@
#include <string.h>
#include <stdlib.h>
#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;
}

View file

@ -2,106 +2,25 @@
#include <string.h> #include <string.h>
#include "fygue.h" #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 /* fygue_dir_read(): directory read implementation
* *
* notes * notes
* - assume that the directory have read permission */ * - assume that the directory have read permission */
int fygue_dir_read( ssize_t fygue_dir_read(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_dir *dir,
struct dirent **dirent, struct dirent **dirent,
size_t size size_t size
) { ) {
struct fygue_fsinfo *fsinfo; if (fsinfo == NULL || dir == NULL)
int rc; FYGUE_RET_ERRNO(EIO);
if (dirent == NULL)
ENOTSUP_IF_NOT_FYGUE(-1); FYGUE_RET_ERRNO(EFAULT);
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { if (size < sizeof *dirent)
errno = EBADF; FYGUE_RET_ERRNO(EINVAL);
return -1; if (dir->pos >= dir->count)
} FYGUE_RET_ERRNO(EIO);
if (dirent == NULL) { *dirent = dir->dirent[dir->pos];
errno = EFAULT; dir->pos += 1;
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;
return sizeof *dirent; return sizeof *dirent;
} }

View file

@ -1,33 +1,58 @@
#include <stdlib.h> #include <stdlib.h>
#include <gint/hardware.h>
#include "fygue.h" #include "fygue.h"
/* fygue_dir_sync(): directory-specific sync */ /* fygue_dir_sync(): directory-specific sync */
int fygue_dir_sync(struct fygue_descriptor *desc) int fygue_dir_sync(
{ struct fygue_fsinfo *fsinfo,
struct fygue_fsinfo *fsinfo; struct fygue_dir *dir
) {
struct fygue_fat_descriptor desc;
int saved_pos;
int rc; int rc;
ENOTSUP_IF_NOT_FYGUE(-1); /* preliminary check */
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { if(gint[HWFS] != HWFS_FUGUE)
errno = EBADF; FYGUE_RET_ERRNO(ENOTSUP);
return -1; if (fsinfo == NULL || dir == NULL)
} FYGUE_RET_ERRNO(EIO);
//if (desc->)
if (fygue_mount(&fsinfo, true)) { /* update FAT-specific information */
errno = EIO; //TODO: assume that the first cluster will remain the same ?
return -1; if (fygue_fat_open(&(fsinfo->fat), dir->path, &desc) != 0)
} FYGUE_RET_ERRNO(ENOENT);
for (int i = 0 ; i < desc->resolve.dir.count ; i++) { if (desc.type != FYGUE_FAT_DESC_TYPE_FILE)
if (desc->resolve.dir.dirent[i] == NULL) FYGUE_RET_ERRNO(EIO);
continue;
free(desc->resolve.dir.dirent[i]);
desc->resolve.dir.dirent[i] = NULL;
}
rc = fygue_fat_dir_sync( rc = fygue_fat_dir_sync(
&(fsinfo->fat), &(fsinfo->fat),
&(desc->resolve.dir.fat) &(desc.dir),
desc.file.cluster_entry
); );
if (rc != 0) 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; return 0;
} }

View file

@ -2,21 +2,16 @@
/* fygue_dir_write(): write directory (EISDIR) */ /* fygue_dir_write(): write directory (EISDIR) */
ssize_t fygue_dir_write( ssize_t fygue_dir_write(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_dir *dir,
void *buffer, void *buffer,
size_t size size_t size
) { ) {
ENOTSUP_IF_NOT_FYGUE(-1); if (fsinfo == NULL || dir == NULL)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) { FYGUE_RET_ERRNO(EIO);
errno = EBADF; if (buffer == NULL)
return -1; FYGUE_RET_ERRNO(EFAULT);
} if (size != 0)
if (buffer == NULL) { FYGUE_RET_ERRNO(EISDIR);
errno = EFAULT; return 0;
return -1;
}
if (size == 0)
return 0;
errno = EISDIR;
return -1;
} }

View file

@ -1,23 +1,15 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "fygue.h" #include "fygue.h"
#include "fat/fat.h" #include "fat/fat.h"
/* fygue_file_close(): close directory */ /* fygue_file_close(): close directory */
int fygue_file_close(struct fygue_descriptor *desc) int fygue_file_close(
{ struct fygue_fsinfo *fsinfo,
struct fygue_fsinfo *fsinfo; struct fygue_file *file
) {
ENOTSUP_IF_NOT_FYGUE(-1); if (fsinfo == NULL || file == NULL)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { FYGUE_RET_ERRNO(EIO);
errno = EBADF; fygue_fat_file_close(&(fsinfo->fat), &(file->fat));
return -1; free(file);
}
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));
return 0; return 0;
} }

View file

@ -2,38 +2,26 @@
/* fygue_file_lseek(): seek file */ /* fygue_file_lseek(): seek file */
off_t fygue_file_lseek( off_t fygue_file_lseek(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_file *file,
off_t offset, off_t offset,
int whence 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) if(whence == SEEK_CUR)
offset += desc->resolve.dir.pos; offset += file->cursor;
if(whence == SEEK_END) if(whence == SEEK_END)
offset += desc->resolve.file.size; offset += file->size;
if(offset < 0 || offset >= desc->resolve.file.size + 1) { if(offset < 0 || (unsigned)offset >= file->size + 1)
errno = EINVAL; FYGUE_RET_ERRNO(EINVAL);
return -1;
} if (fygue_fat_file_seek(&(fsinfo->fat), &(file->fat), offset) != 0)
desc->resolve.file.cursor = offset; FYGUE_RET_ERRNO(EIO);
fygue_fat_file_seek(
&(fsinfo->fat), file->cursor = offset;
&(desc->resolve.file.fat), return file->cursor;
offset
);
return desc->resolve.file.cursor;
} }

View file

@ -0,0 +1,21 @@
#include <string.h>
#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;
}

View file

@ -1,35 +1,19 @@
#include <stdlib.h>
#include <string.h>
#include "fygue.h" #include "fygue.h"
/* fygue_file_read(): write directory (EISDIR) */ /* fygue_file_read(): read file data */
ssize_t fygue_file_read( ssize_t fygue_file_read(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_file *file,
void *buffer, void *buffer,
size_t size size_t size
) { ) {
struct fygue_fsinfo *fsinfo; if (fsinfo == NULL || file == NULL)
FYGUE_RET_ERRNO(EIO);
ENOTSUP_IF_NOT_FYGUE(-1); if (buffer == NULL)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { FYGUE_RET_ERRNO(EFAULT);
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;
}
return fygue_fat_file_read( return fygue_fat_file_read(
&(fsinfo->fat), &(fsinfo->fat),
&(desc->resolve.file.fat), &(file->fat),
buffer, buffer,
size size
); );

View file

@ -1,26 +1,30 @@
#include <gint/hardware.h>
#include "fygue.h" #include "fygue.h"
/* fygue_file_sync(): file-specific sync */ /* fygue_file_sync(): file-specific sync */
int fygue_file_sync(struct fygue_descriptor *desc) int fygue_file_sync(
{ struct fygue_fsinfo *fsinfo,
struct fygue_fsinfo *fsinfo; struct fygue_file *file
) {
struct fygue_fat_descriptor desc;
int rc; int rc;
ENOTSUP_IF_NOT_FYGUE(-1); if(gint[HWFS] != HWFS_FUGUE)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { FYGUE_RET_ERRNO(ENOTSUP);
errno = EBADF; if (fsinfo == NULL || file == NULL)
return -1; FYGUE_RET_ERRNO(EIO);
}
if (fygue_mount(&fsinfo, true)) { //TODO: assume that the first cluster will remain the same ?
errno = EIO; if (fygue_fat_open(&(fsinfo->fat), file->path, &desc) != 0)
return -1; FYGUE_RET_ERRNO(ENOENT);
} if (desc.type != FYGUE_FAT_DESC_TYPE_FILE)
// nothing to sync in high-level FYGUE_RET_ERRNO(EIO);
rc = fygue_fat_file_sync( rc = fygue_fat_file_sync(
&(fsinfo->fat), &(fsinfo->fat),
&(desc->resolve.file.fat) &(desc.file),
desc.file.cluster_entry
); );
if (rc != 0) if (rc != 0)
return -1; FYGUE_RET_ERRNO(EIO);
return 0; return 0;
} }

View file

@ -2,21 +2,16 @@
/* fygue_file_write(): write directory (EISDIR) */ /* fygue_file_write(): write directory (EISDIR) */
ssize_t fygue_file_write( ssize_t fygue_file_write(
struct fygue_descriptor *desc, struct fygue_fsinfo *fsinfo,
struct fygue_file *file,
void *buffer, void *buffer,
size_t size size_t size
) { ) {
ENOTSUP_IF_NOT_FYGUE(-1); if (fsinfo == NULL || file == NULL)
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_FILE) { FYGUE_RET_ERRNO(EIO);
errno = EBADF; if (buffer == NULL)
return -1; FYGUE_RET_ERRNO(EFAULT);
} if (size != 0)
if (buffer == NULL) { FYGUE_RET_ERRNO(EROFS);
errno = EFAULT; return 0;
return -1;
}
if (size == 0)
return 0;
errno = EROFS;
return -1;
} }

View file

@ -0,0 +1,45 @@
#include <stdlib.h>
#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;
}

View file

@ -2,65 +2,86 @@
#include <stdlib.h> #include <stdlib.h>
#include <gint/gint.h> #include <gint/gint.h>
#include <gint/bfile.h> #include <gint/bfile.h>
#include <gint/hardware.h>
#include "../fugue/fugue.h" #include "../fugue/fugue.h"
#include "fygue.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 */ /* fygue_open(): open primitive */
int fygue_open(char const *path, int flags, GUNUSED mode_t mode) int fygue_open(char const *path, int flags, GUNUSED mode_t mode)
{ {
struct fygue_descriptor *desc; struct fygue_descriptor desc;
struct fygue_resolve resolve; fs_descriptor_t gint_desc;
fs_descriptor_t data; int exists;
if ((flags & O_RDWR) || (flags & O_WRONLY)) { /* preliminary checks */
errno = EROFS; if(gint[HWFS] != HWFS_FUGUE)
return -1; FYGUE_RET_ERRNO(ENOTSUP);
} if ((flags & O_RDWR) || (flags & O_WRONLY))
ENOTSUP_IF_NOT_FYGUE(-1); FYGUE_RET_ERRNO(EROFS);
/* resolve the entry */ /* 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 opening fails and no explicit file creation is required, fail */
if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY)))) { if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY))))
errno = ENOENT; FYGUE_RET_ERRNO(ENOENT);
return -1;
}
/* if opening fails and the previous check as not returned an error, /* 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 * it is certainly because of a creation request. We are a read-only
* file-system, so, fail */ * file-system, so, fail */
if (exists < 0) { if (exists < 0)
errno = EROFS; FYGUE_RET_ERRNO(EROFS);
return -1;
}
/* If the entry exists and O_EXCL was requested, fail. /* If the entry exists and O_EXCL was requested, fail.
* note that Exclusive open means no sense unless creation is also * note that Exclusive open means no sense unless creation is also
* requested */ * requested */
if(exists >= 0 && (flags & O_EXCL)) { if(exists >= 0 && (flags & O_EXCL))
errno = EEXIST; FYGUE_RET_ERRNO(EEXIST);
return -1;
}
/* generate the final file descriptor */ /* generate the final file descriptor */
desc = calloc(1, sizeof(struct fygue_descriptor)); gint_desc.type = &fygue_file_descriptor_type;
if (desc == NULL) { gint_desc.data = calloc(1, sizeof(struct fygue_descriptor));
errno = ENOMEM; if (gint_desc.data == NULL)
return -1; 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); return fs_create_descriptor(&gint_desc);
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);
} }

View file

@ -1,35 +1,22 @@
#include <gint/hardware.h>
#include "fygue.h" #include "fygue.h"
#include "fat/fat.h" #include "fat/fat.h"
/* fygue_stat(): stat primitive */ /* fygue_stat(): stat primitive */
int fygue_stat(char const * const path, struct stat *statbuf) int fygue_stat(char const * const path, struct stat *statbuf)
{ {
struct fygue_resolve resolve; struct fygue_descriptor desc;
struct fygue_fsinfo *fsinfo; struct fygue_fsinfo *fsinfo;
ENOTSUP_IF_NOT_FYGUE(-1); if(gint[HWFS] != HWFS_FUGUE)
if (path == NULL || statbuf == NULL) { FYGUE_RET_ERRNO(ENOTSUP);
errno = EFAULT; if (path == NULL || statbuf == NULL)
return -1; FYGUE_RET_ERRNO(EFAULT);
} if (fygue_mount(&fsinfo) != 0)
if (fygue_mount(&fsinfo, true) != 0) { FYGUE_RET_ERRNO(EIO);
errno = EIO; if (fygue_open_resolve(path, &desc) != 0)
return -1; FYGUE_RET_ERRNO(ENOENT);
} if (desc.type == FYGUE_DESC_TYPE_DIR)
if (fygue_resolve(path, &resolve) != 0) { return fygue_fat_dir_stat(&(fsinfo->fat), &(desc.dir.fat), statbuf);
errno = ENOENT; return fygue_fat_file_stat(&(fsinfo->fat), &(desc.file.fat), statbuf);
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
);
} }

View file

@ -1,16 +1,20 @@
#include <gint/hardware.h>
#include "fygue.h" #include "fygue.h"
/* fygue_syncfs() - request filesystem re-synchronisation */
int fygue_syncfs(void *data) int fygue_syncfs(void *data)
{ {
struct fygue_fsinfo *fsinfo; struct fygue_fsinfo *fsinfo;
struct fygue_descriptor *descriptor; struct fygue_descriptor *desc;
if(gint[HWFS] != HWFS_FUGUE)
FYGUE_RET_ERRNO(ENOTSUP);
if (data == NULL) if (data == NULL)
return -1; FYGUE_RET_ERRNO(EBADF);
if (fygue_mount(&fsinfo, false) != 0) if (fygue_mount(&fsinfo) != 0)
return -2; FYGUE_RET_ERRNO(EIO);
descriptor = data; desc = data;
descriptor->dirty = true; desc->dirty = true;
fsinfo->dirty = true; fsinfo->dirty = true;
return 0; return 0;
} }