fygue: support open() primitive

This commit is contained in:
Yann MAGNIN 2025-04-03 14:22:02 +02:00
parent 6d99494d30
commit e4e09052fc
No known key found for this signature in database
GPG key ID: D82629D933EADC59
9 changed files with 168 additions and 119 deletions

View file

@ -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;

View file

@ -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 */

View file

@ -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;
}

View file

@ -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);
}

View file

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

View file

@ -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

View file

@ -1,83 +1,61 @@
#if 0
#include <string.h>
#include <stdlib.h>
#include <gint/gint.h>
#include <gint/bfile.h>
#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

View file

@ -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;

View file

@ -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;
}