diff --git a/src/fs/fygue/fat/cluster.c b/src/fs/fygue/fat/cluster.c index 6774a48..c3b26e6 100644 --- a/src/fs/fygue/fat/cluster.c +++ b/src/fs/fygue/fat/cluster.c @@ -7,8 +7,8 @@ // Public //--- -/* fygue_fat_cluster_next() - find the next cluster ID of a file */ -int fygue_fat_cluster_next(struct fygue_fat *fat, int *cluster_current) +/* fygue_fat_cluster_get_next() - find the next cluster ID of a file */ +int fygue_fat_cluster_get_next(struct fygue_fat *fat, int *cluster_current) { uint16_t *fat0; int cluster; diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index b695e4d..1f1e17e 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -52,7 +52,6 @@ struct fygue_fat_dirent unsigned int cluster_id; }; - /* fygue_fat_dir - fygue directory information */ struct fygue_fat_dir { @@ -67,6 +66,25 @@ struct fygue_fat_dir bool dirty; }; +/* fygue_fat_file: file information needed to perform IO primitives */ +struct fygue_fat_file +{ + int todo; +}; + +/* fygue_fat_resolve: internal resolve information */ +struct fygue_fat_resolve +{ + enum { + FYGUE_FAT_FILE_TYPE_FILE, + FYGUE_FAT_FILE_TYPE_DIR, + } type; + union { + struct fygue_fat_file file; + struct fygue_fat_dir dir; + }; +}; + /* fygue_fat_init_cold() - fully initialize the FAT information */ extern int fygue_fat_init_cold(struct fygue_fat *fat); @@ -77,7 +95,7 @@ extern int fygue_fat_init_hot(struct fygue_fat *fat); extern int fygue_fat_resolve( struct fygue_fat *fat, char const * const path, - struct fygue_fat_dirent *dirent + struct fygue_fat_resolve *resolve ); /* fygue_fat_readdir(): readdir primitive */ diff --git a/src/fs/fygue/fat/initialize.c b/src/fs/fygue/fat/initialize.c index 32b3fd4..d4d24ea 100644 --- a/src/fs/fygue/fat/initialize.c +++ b/src/fs/fygue/fat/initialize.c @@ -193,3 +193,11 @@ int fygue_fat_init_cold(struct fygue_fat *fat) } return 0; } + +/* fygue_fat_init_hot(): re-initialize the FAT information */ +int fygue_fat_init_hot(struct fygue_fat *fat) +{ + //FIXME: implement + (void)fat; + return -3; +} diff --git a/src/fs/fygue/fat/resolve.c b/src/fs/fygue/fat/resolve.c index 1a91174..6f69faf 100644 --- a/src/fs/fygue/fat/resolve.c +++ b/src/fs/fygue/fat/resolve.c @@ -11,14 +11,18 @@ * - assume that prefix is not NULL and clean * - assume that size is not NULL * - assume that prefix can start with '/' */ -static int _fygue_path_get_name(char const **prefix, size_t *len) -{ +static int _fygue_path_get_name( + char const **prefix, + char const **filename, + size_t *len +) { while ((*prefix)[0] == '/') { *prefix = &((*prefix)[1]); } if ((*prefix)[0] == '\0') return -1; *len = 0; + *filename = *prefix; while ((*prefix)[0] != '\0' && (*prefix)[0] != '/') { *len += 1; *prefix = &((*prefix)[1]); @@ -38,6 +42,8 @@ static int _fygue_dirent_resolve( dir->cluster_entry = 0; dir->root_dirent_count = fat->RootEntCount; } else { + if ((dirent->type & 0x10) == 0x00) + return -1; dir->cluster_entry = dirent->cluster_id; dir->root_dirent_count = 0; } @@ -78,10 +84,28 @@ 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_dirent *dirent +) { + resolve->type = FYGUE_FAT_FILE_TYPE_DIR; + if (_fygue_dirent_resolve(fat, &(resolve->dir), dirent) == 0) + return 0; + resolve->type = FYGUE_FAT_FILE_TYPE_FILE; + // todo: support IO file information + return 0; +} + //--- // Public //--- +char const *debug_prefix = ""; +char const *debug_start = ""; +size_t debug_len = 0; + /* fygue_fat_resolve(): resolve any path provided * * notes @@ -89,40 +113,42 @@ static int _fygue_dirent_find( int fygue_fat_resolve( struct fygue_fat *fat, char const * const path, - struct fygue_fat_dirent *dirent + struct fygue_fat_resolve *resolve ) { + struct fygue_fat_dirent dirent; struct fygue_fat_dir dir; char const *prefix; + char const *start; size_t len; bool is_root; - if (fat == NULL || path == NULL || dirent == NULL) + if (fat == NULL || path == NULL || resolve == NULL) return -1; if (path[0] != '/') return -1; - if (_fygue_dirent_resolve(fat, &dir, NULL) != 0) - return -3; prefix = path; is_root = true; while (true) { - if (_fygue_path_get_name(&prefix, &len) != 0) + if (is_root) { + if (_fygue_dirent_resolve(fat, &dir, NULL) != 0) + return -3; + if (_fygue_path_get_name(&prefix, &start, &len) != 0) + break; + is_root = false; + continue; + } + debug_prefix = prefix; + debug_start = start; + debug_len = len; + if (_fygue_dirent_find(fat, &dir, &dirent, start, len) != 0) + return -4; + if (_fygue_path_get_name(&prefix, &start, &len) != 0) break; - is_root = false; - if (_fygue_dirent_find(fat, &dir, dirent, prefix, len) != 0) - return -4; - if (_fygue_dirent_resolve(fat, &dir, dirent) != 0) - return -4; + if (_fygue_dirent_resolve(fat, &dir, &dirent) != 0) + return -5; } if (is_root) - { - memset(dirent, 0x00, sizeof(struct fygue_fat_dirent)); - dirent->name[0] = '/'; - dirent->name[1] = '\0'; - dirent->type = 0x10; - dirent->size = sizeof(struct fygue_fat_dirent); - dirent->meta_addr = dir.dirent_current_addr; - dirent->cluster_id = dir.cluster_entry; - } - return 0; + return _fygue_resolve_set(fat, resolve, NULL); + return _fygue_resolve_set(fat, resolve, &dirent); } diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index e68805f..691e79a 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -1,4 +1,5 @@ #include +#include #include "fygue.h" //--- @@ -45,23 +46,35 @@ int fygue_mount(struct fygue_fsinfo **fsinfo, bool refresh) * - 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, - int *type, - struct fygue_stat *stat -) { +int fygue_resolve(char const * const path, struct fygue_resolve *resolve) +{ struct fygue_fsinfo *fsinfo; - struct fygue_fat_dirent dirent; + struct fygue_fat_resolve fat_resolve; - if (path == NULL || path[0] != '\\') + if (path == NULL || path[0] != '/' || resolve == NULL) return -1; if (fygue_mount(&fsinfo, true) != 0) return -2; - if (fygue_fat_resolve(&(fsinfo->fat), path, &dirent) != 0) - return -3; - (void)type; - (void)stat; - // todo: convert FAT dirent into Fygue stat + int rc = fygue_fat_resolve(&(fsinfo->fat), path, &fat_resolve); + if (rc < 0) + return rc; + 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; + memcpy( + &(resolve->dir.fat), + &(fat_resolve.dir), + sizeof(struct fygue_fat_dir) + ); + } return 0; } diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h index 5659f33..f56e91f 100644 --- a/src/fs/fygue/fygue.h +++ b/src/fs/fygue/fygue.h @@ -62,28 +62,42 @@ struct fygue_fsinfo bool dirty; }; -/* fygue_stat: internals file information */ -struct fygue_stat { - int type; +/* fygue_resolve: internals file information */ +struct fygue_resolve { + enum { + FYGUE_FILE_TYPE_FILE, + FYGUE_FILE_TYPE_DIR, + } type; union { struct { - int file; - }; + off_t cursor; + struct fygue_fat_file fat; + } file; struct { - int dir; - }; + struct fygue_fat_dir fat; + } dir; }; }; -/* fygue_file_descriptor: internal file descriptor information */ -struct fygue_file_descriptor +/* fygue_descriptor: internal file descriptor information */ +struct fygue_descriptor { + struct fygue_resolve resolve; + char const *path; + int flags; bool dirty; }; /* fygue_mount(): mount and return the filesystem info */ extern int fygue_mount(struct fygue_fsinfo **fsinfo, bool refresh); + +/* fygue_resolve() - try to resolve path */ +extern int fygue_resolve( + char const * const path, + struct fygue_resolve *resolve +); + #ifdef __cplusplus } #endif diff --git a/src/fs/fygue/fygue_open.c b/src/fs/fygue/fygue_open.c index 440fa94..8011574 100644 --- a/src/fs/fygue/fygue_open.c +++ b/src/fs/fygue/fygue_open.c @@ -1,83 +1,61 @@ -#if 0 +#include +#include #include #include -#include "../fugue/util.h" +#include "../fugue/fugue.h" #include "fygue.h" -#include "utils.h" +/* fygue_open(): open primitive */ int fygue_open(char const *path, int flags, GUNUSED mode_t mode) { - int rc; + struct fygue_descriptor *desc; + struct fygue_resolve resolve; + fs_descriptor_t data; ENOTSUP_IF_NOT_FYGUE(-1); - /* Exclusive open means no sense unless creation is also requested */ - bool excl = (flags & O_EXCL) && (flags & O_CREAT); - /* Truncation requires the file to be removed/recreated */ - bool trunc = (flags & O_TRUNC) && (flags & O_CREAT); + /* resolve the entry */ + int exists = fygue_resolve(path, &resolve); - /* stat the entry */ - exists = fygue_resolve(path); + /* if opening fails and no explicit file creation is required, fail */ + if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY)))) { + errno = ENOENT; + return exists; + } - /* If the entry exists and O_EXCL was requested, fail. */ - if(exists && excl) { + /* 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 exists; + } + + /* 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 the entry is not a directory but O_DIRECTORY is set, fail. If the - directory doesn't exist, we fail regardless of O_CREAT. */ - if((flags & O_DIRECTORY) && type != BFile_Type_Directory) { - errno = (exists ? ENOTDIR : ENOENT); - return -1; - } - - /* If the entry is a directory, open it as such */ - if(type == BFile_Type_Directory) { - void *dp = fugue_dir_explore(path); - if(!dp) { - rc = -1; - goto end; - } - fs_descriptor_t data = { - .type = &fugue_dir_descriptor_type, - .data = dp, - }; - return = fs_create_descriptor(&data); - } - - /* prepare Fugue/Casio path */ - uint16_t *fcpath = fs_path_normalize_fc(path); - if(fcpath == NULL) { + /* generate the final file descriptor */ + desc = calloc(1, sizeof(struct fygue_descriptor)); + if (desc == NULL) { errno = ENOMEM; return -1; } - - /* If O_TRUNC is requested and either the file exists or we can create - * it, remove it. (If fugue_fd < 0 an opening error might still have - * occurred so we delete it just in case.) */ - if((flags & O_TRUNC) && (fugue_fd >= 0 || (flags & O_CREAT))) { - gint_world_enter(GINT_WORLD_OS); - BFile_Remove(fcpath); - gint_world_leave(); - fugue_fd = BFile_EntryNotFound; - } - - /* If the file does not exist and O_CREAT is set, create it */ - if((flags & O_CREAT) && ((flags & O_TRUNC) || fugue_fd < 0)) - { - int new_file_size = 0; - gint_world_enter(GINT_WORLD_OS); - int err = BFile_Create(fcpath, BFile_File, &new_file_size); - gint_world_leave(); - if(err < 0) { - errno = bfile_error_to_errno(err); + 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; } - -end: - free(fcpath); - return rc; + return fs_create_descriptor(&data); } -#endif diff --git a/src/fs/fygue/fygue_syncfs.c b/src/fs/fygue/fygue_syncfs.c index 9a596cd..a6403c3 100644 --- a/src/fs/fygue/fygue_syncfs.c +++ b/src/fs/fygue/fygue_syncfs.c @@ -3,7 +3,7 @@ int fygue_syncfs(void *data) { struct fygue_fsinfo *fsinfo; - struct fygue_file_descriptor *descriptor; + struct fygue_descriptor *descriptor; if (data == NULL) return -1; diff --git a/src/fs/open.c b/src/fs/open.c index ac1c4b4..a795b2e 100644 --- a/src/fs/open.c +++ b/src/fs/open.c @@ -12,20 +12,12 @@ int open(char const *path, int flags, ...) /* Standard open() use Fugue filesystem if a write operation * is requested, otherwise use the Fygue filesystem */ - int rc = 0; + int rc = -1; if ((flags & O_WRONLY) || (flags & O_RDWR)) { rc = fugue_open(path, flags, mode); + fs_fygue_sync(); } else { rc = fygue_open(path, flags, mode); } - /* Even with Fygue open primitive, request a sync for all Fygue's - * descriptor because when some flags are set (e.g O_CREATE) Fygue - * invoke BFile_*() syscall that perform IO operation. - * - * Note that Fygue's open() primitive with perform a "lazy" open - * operation by simply ensure that the file exists and mark the file - * descriptor as dirty to force internal data refresh on the next - * Fygue's IO operation */ - fs_fygue_sync(); return rc; }