mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-05-18 15:29:16 +02:00
fygue: support open() primitive
This commit is contained in:
parent
6d99494d30
commit
e4e09052fc
9 changed files with 168 additions and 119 deletions
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
if (_fygue_dirent_find(fat, &dir, dirent, prefix, len) != 0)
|
||||
return -4;
|
||||
if (_fygue_dirent_resolve(fat, &dir, dirent) != 0)
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue