mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-05-18 23:39:17 +02:00
fygue: switch tabs to spaces :)
This commit is contained in:
parent
817e654e74
commit
7ff93e79f0
61 changed files with 2094 additions and 2101 deletions
|
@ -12,13 +12,13 @@ int close(int fd)
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if(d->type->close == NULL)
|
if(d->type->close == NULL)
|
||||||
goto end;
|
goto end;
|
||||||
/* Fugue's close primitive can flush pending IO write operation. So, we
|
/* Fugue's close primitive can flush pending IO write operation. So, we
|
||||||
* are in the same situation than the write() primitive: force-sync
|
* are in the same situation than the write() primitive: force-sync
|
||||||
* Fygue's descriptor to ensure data intergrity */
|
* Fygue's descriptor to ensure data intergrity */
|
||||||
rc = d->type->close(d->data);
|
rc = d->type->close(d->data);
|
||||||
if (fs_descriptor_is_fugue(d))
|
if (fs_descriptor_is_fugue(d))
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
|
|
||||||
end:
|
end:
|
||||||
fs_free_descriptor(fd);
|
fs_free_descriptor(fd);
|
||||||
|
|
30
src/fs/fs.c
30
src/fs/fs.c
|
@ -50,29 +50,29 @@ void fs_free_descriptor(int fd)
|
||||||
|
|
||||||
bool fs_descriptor_is_fugue(fs_descriptor_t const *desc)
|
bool fs_descriptor_is_fugue(fs_descriptor_t const *desc)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
(desc->type == &fugue_dir_descriptor_type) ||
|
(desc->type == &fugue_dir_descriptor_type) ||
|
||||||
(desc->type == &fugue_descriptor_type)
|
(desc->type == &fugue_descriptor_type)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_descriptor_is_fygue(fs_descriptor_t const *desc)
|
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_file_descriptor_type)
|
(desc->type == &fygue_file_descriptor_type)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_fygue_sync(void)
|
void fs_fygue_sync(void)
|
||||||
{
|
{
|
||||||
fygue_sync();
|
fygue_sync();
|
||||||
for (int i = 3 ; i < FS_FD_MAX ; i++) {
|
for (int i = 3 ; i < FS_FD_MAX ; i++) {
|
||||||
if (fdtable[i].type == NULL)
|
if (fdtable[i].type == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (fs_descriptor_is_fygue(fdtable[i].data))
|
if (fs_descriptor_is_fygue(fdtable[i].data))
|
||||||
fygue_syncfs(fdtable[i].data);
|
fygue_syncfs(fdtable[i].data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int open_generic(fs_descriptor_type_t const *type, void *data, int fd)
|
int open_generic(fs_descriptor_type_t const *type, void *data, int fd)
|
||||||
|
|
|
@ -12,7 +12,7 @@ int BFile_Ext_Stat(uint16_t const *path, int *type, int *size)
|
||||||
uint16_t found_file[256];
|
uint16_t found_file[256];
|
||||||
struct BFile_FileInfo fileinfo;
|
struct BFile_FileInfo fileinfo;
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
rc = BFile_FindFirst(path, &search_handle, found_file, &fileinfo);
|
rc = BFile_FindFirst(path, &search_handle, found_file, &fileinfo);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
if(type) *type = -1;
|
if(type) *type = -1;
|
||||||
|
@ -26,6 +26,6 @@ int BFile_Ext_Stat(uint16_t const *path, int *type, int *size)
|
||||||
}
|
}
|
||||||
|
|
||||||
BFile_FindClose(search_handle);
|
BFile_FindClose(search_handle);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
ssize_t fugue_read(void *data0, void *buf, size_t size)
|
ssize_t fugue_read(void *data0, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
|
|
||||||
fugue_fd_t *data = data0;
|
fugue_fd_t *data = data0;
|
||||||
int fugue_fd = data->fd;
|
int fugue_fd = data->fd;
|
||||||
|
@ -32,10 +32,10 @@ ssize_t fugue_read(void *data0, void *buf, size_t size)
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
size = -1;
|
size = -1;
|
||||||
} else {
|
} else {
|
||||||
data->pos += rc;
|
data->pos += rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ ssize_t fugue_write(void *data0, const void *buf, size_t size)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
while(written < size) {
|
while(written < size) {
|
||||||
size_t block_size = min(size - written, alloc_size);
|
size_t block_size = min(size - written, alloc_size);
|
||||||
memcpy(ram, buf + written, block_size);
|
memcpy(ram, buf + written, block_size);
|
||||||
|
@ -91,22 +91,22 @@ ssize_t fugue_write(void *data0, const void *buf, size_t size)
|
||||||
/* Partial write */
|
/* Partial write */
|
||||||
if(rc < (int)block_size) break;
|
if(rc < (int)block_size) break;
|
||||||
}
|
}
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
|
|
||||||
free(ram);
|
free(ram);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
/* Otherwise, we can write normally */
|
/* Otherwise, we can write normally */
|
||||||
else {
|
else {
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Write(fugue_fd, buf, size);
|
int rc = BFile_Write(fugue_fd, buf, size);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
data->pos += rc;
|
data->pos += rc;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,20 +118,20 @@ off_t fugue_lseek(void *data0, off_t offset, int whence)
|
||||||
// TODO: fugue_lseek: CP400 optimization with native whence?
|
// TODO: fugue_lseek: CP400 optimization with native whence?
|
||||||
#if GINT_OS_CP
|
#if GINT_OS_CP
|
||||||
whence = (whence == SEEK_SET) ? BFileCP_SEEK_SET :
|
whence = (whence == SEEK_SET) ? BFileCP_SEEK_SET :
|
||||||
(whence == SEEK_CUR) ? BFileCP_SEEK_CUR :
|
(whence == SEEK_CUR) ? BFileCP_SEEK_CUR :
|
||||||
BFileCP_SEEK_END;
|
BFileCP_SEEK_END;
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Seek(fugue_fd, offset, whence);
|
int rc = BFile_Seek(fugue_fd, offset, whence);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
rc = -1;
|
rc = -1;
|
||||||
} else {
|
} else {
|
||||||
data->pos = rc;
|
data->pos = rc;
|
||||||
}
|
}
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
return rc;
|
return rc;
|
||||||
#else
|
#else
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int filesize = BFile_Size(fugue_fd);
|
int filesize = BFile_Size(fugue_fd);
|
||||||
|
|
||||||
if(whence == SEEK_CUR)
|
if(whence == SEEK_CUR)
|
||||||
|
@ -148,10 +148,10 @@ off_t fugue_lseek(void *data0, off_t offset, int whence)
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
offset = -1;
|
offset = -1;
|
||||||
} else {
|
} else {
|
||||||
data->pos = offset;
|
data->pos = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
|
|
||||||
/* rc is the amount of space left in the file (including pre-allocated
|
/* rc is the amount of space left in the file (including pre-allocated
|
||||||
space), so instead just return offset directly */
|
space), so instead just return offset directly */
|
||||||
|
@ -161,7 +161,7 @@ off_t fugue_lseek(void *data0, off_t offset, int whence)
|
||||||
|
|
||||||
int fugue_close(void *data0)
|
int fugue_close(void *data0)
|
||||||
{
|
{
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
|
|
||||||
fugue_fd_t *data = data0;
|
fugue_fd_t *data = data0;
|
||||||
int fugue_fd = data->fd;
|
int fugue_fd = data->fd;
|
||||||
|
@ -171,9 +171,9 @@ int fugue_close(void *data0)
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
rc = -1;
|
rc = -1;
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(data);
|
free(data);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ void *fugue_dir_explore(char const *path)
|
||||||
/* We allocate by batches of 8 */
|
/* We allocate by batches of 8 */
|
||||||
int sd=-1, rc, allocated=0;
|
int sd=-1, rc, allocated=0;
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
|
|
||||||
dir_t *dp = malloc(sizeof *dp);
|
dir_t *dp = malloc(sizeof *dp);
|
||||||
if(!dp) goto alloc_failure;
|
if(!dp) goto alloc_failure;
|
||||||
|
@ -165,6 +165,6 @@ end:
|
||||||
free(fc_path);
|
free(fc_path);
|
||||||
if(sd >= 0)
|
if(sd >= 0)
|
||||||
BFile_FindClose(sd);
|
BFile_FindClose(sd);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
return dp;
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ int fugue_mkdir(char const *path, GUNUSED mode_t mode)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Mkdir(normpath);
|
int rc = BFile_Mkdir(normpath);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(normpath);
|
free(normpath);
|
||||||
#else
|
#else
|
||||||
uint16_t *fcpath = fs_path_normalize_fc(path);
|
uint16_t *fcpath = fs_path_normalize_fc(path);
|
||||||
|
@ -28,15 +28,15 @@ int fugue_mkdir(char const *path, GUNUSED mode_t mode)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Create(fcpath, BFile_Folder, NULL);
|
int rc = BFile_Create(fcpath, BFile_Folder, NULL);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(fcpath);
|
free(fcpath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode)
|
||||||
bfile_mode |= BFile_AppendFlag;
|
bfile_mode |= BFile_AppendFlag;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
|
|
||||||
/* Stat the entry. A special case is needed for the root, which doesn't
|
/* Stat the entry. A special case is needed for the root, which doesn't
|
||||||
respond well. fs_path_normalize_fc() normalizes the path so we just
|
respond well. fs_path_normalize_fc() normalizes the path so we just
|
||||||
|
@ -171,7 +171,7 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
#if GINT_OS_CP
|
#if GINT_OS_CP
|
||||||
free(normpath);
|
free(normpath);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,9 +12,9 @@ int fugue_rename(char const *oldpath, char const *newpath)
|
||||||
ENOTSUP_IF_NOT_FUGUE(-1);
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
#if GINT_OS_CP
|
#if GINT_OS_CP
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Rename(oldpath, newpath);
|
int rc = BFile_Rename(oldpath, newpath);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
#else
|
#else
|
||||||
u16 *fcpath_1 = fs_path_normalize_fc(oldpath);
|
u16 *fcpath_1 = fs_path_normalize_fc(oldpath);
|
||||||
if(!fcpath_1) {
|
if(!fcpath_1) {
|
||||||
|
@ -27,9 +27,9 @@ int fugue_rename(char const *oldpath, char const *newpath)
|
||||||
free(fcpath_1);
|
free(fcpath_1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Rename(fcpath_1, fcpath_2);
|
int rc = BFile_Rename(fcpath_1, fcpath_2);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(fcpath_1);
|
free(fcpath_1);
|
||||||
free(fcpath_2);
|
free(fcpath_2);
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,5 +38,5 @@ int fugue_rename(char const *oldpath, char const *newpath)
|
||||||
errno = bfile_error_to_errno(rc);
|
errno = bfile_error_to_errno(rc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,9 @@ int fugue_rmdir(char const *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GINT_OS_CP
|
#if GINT_OS_CP
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Remove(path);
|
int rc = BFile_Remove(path);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
#else
|
#else
|
||||||
uint16_t *fcpath = fs_path_normalize_fc(path);
|
uint16_t *fcpath = fs_path_normalize_fc(path);
|
||||||
if(!fcpath) {
|
if(!fcpath) {
|
||||||
|
@ -46,9 +46,9 @@ int fugue_rmdir(char const *path)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
int rc = BFile_Remove(fcpath);
|
int rc = BFile_Remove(fcpath);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(fcpath);
|
free(fcpath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ int fugue_stat(char const * restrict path, struct stat * restrict statbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
int type, size, rc;
|
int type, size, rc;
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
rc = BFile_Ext_Stat(fcpath, &type, &size);
|
rc = BFile_Ext_Stat(fcpath, &type, &size);
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(fcpath);
|
free(fcpath);
|
||||||
|
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ int fugue_unlink(char const *path)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gint_world_enter(GINT_WORLD_OS);
|
gint_world_enter(GINT_WORLD_OS);
|
||||||
|
|
||||||
int type, size, rc;
|
int type, size, rc;
|
||||||
rc = BFile_Ext_Stat(fcpath, &type, &size);
|
rc = BFile_Ext_Stat(fcpath, &type, &size);
|
||||||
|
@ -54,7 +54,7 @@ int fugue_unlink(char const *path)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
gint_world_leave();
|
gint_world_leave();
|
||||||
free(fcpath);
|
free(fcpath);
|
||||||
#if GINT_OS_CP
|
#if GINT_OS_CP
|
||||||
free(normpath);
|
free(normpath);
|
||||||
|
|
|
@ -12,47 +12,47 @@ int bfile_error_to_errno(int e)
|
||||||
{
|
{
|
||||||
#if GINT_OS_CP
|
#if GINT_OS_CP
|
||||||
switch(e) {
|
switch(e) {
|
||||||
case BFileCP_ENOMEM: return ENOENT;
|
case BFileCP_ENOMEM: return ENOENT;
|
||||||
case BFileCP_EINVAL: return EINVAL;
|
case BFileCP_EINVAL: return EINVAL;
|
||||||
case BFileCP_EDEVFAIL: return EIO;
|
case BFileCP_EDEVFAIL: return EIO;
|
||||||
case BFileCP_EMOUNTED: return ENODEV;
|
case BFileCP_EMOUNTED: return ENODEV;
|
||||||
case BFileCP_EACCES: return EACCES;
|
case BFileCP_EACCES: return EACCES;
|
||||||
case BFileCP_EBADFSID: return ENODEV;
|
case BFileCP_EBADFSID: return ENODEV;
|
||||||
case BFileCP_ENOVOLUME: return ENODEV;
|
case BFileCP_ENOVOLUME: return ENODEV;
|
||||||
case BFileCP_ENOPATH: return ENOENT;
|
case BFileCP_ENOPATH: return ENOENT;
|
||||||
case BFileCP_EEXIST: return EEXIST;
|
case BFileCP_EEXIST: return EEXIST;
|
||||||
case BFileCP_ENAMETOOLONG: return EINVAL;
|
case BFileCP_ENAMETOOLONG: return EINVAL;
|
||||||
case BFileCP_EOUTOFBOUND: return EINVAL;
|
case BFileCP_EOUTOFBOUND: return EINVAL;
|
||||||
case BFileCP_EUNFORMAT: return EINVAL;
|
case BFileCP_EUNFORMAT: return EINVAL;
|
||||||
case BFileCP_ENOSPC: return ENOSPC;
|
case BFileCP_ENOSPC: return ENOSPC;
|
||||||
case BFileCP_ENOENT: return ENOENT;
|
case BFileCP_ENOENT: return ENOENT;
|
||||||
case BFileCP_EISDIRECTORY: return EISDIR;
|
case BFileCP_EISDIRECTORY: return EISDIR;
|
||||||
case BFileCP_ESHARE: return EINVAL;
|
case BFileCP_ESHARE: return EINVAL;
|
||||||
case BFileCP_EMFILE: return EMFILE;
|
case BFileCP_EMFILE: return EMFILE;
|
||||||
case BFileCP_EBADF: return EBADF;
|
case BFileCP_EBADF: return EBADF;
|
||||||
case BFileCP_EEOF: return EINVAL;
|
case BFileCP_EEOF: return EINVAL;
|
||||||
case BFileCP_ENOTEMPTY: return EINVAL;
|
case BFileCP_ENOTEMPTY: return EINVAL;
|
||||||
case BFileCP_ECLUSTERSIZEMISMATCH: return EINVAL;
|
case BFileCP_ECLUSTERSIZEMISMATCH: return EINVAL;
|
||||||
case BFileCP_ESYSTEM: return EINVAL;
|
case BFileCP_ESYSTEM: return EINVAL;
|
||||||
default: return errno;
|
default: return errno;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* TODO: Find BFile code for too many fds and map it to ENFILE. */
|
/* TODO: Find BFile code for too many fds and map it to ENFILE. */
|
||||||
switch(e) {
|
switch(e) {
|
||||||
case BFile_EntryNotFound: return ENOENT;
|
case BFile_EntryNotFound: return ENOENT;
|
||||||
case BFile_IllegalPath: return EINVAL;
|
case BFile_IllegalPath: return EINVAL;
|
||||||
case BFile_DeviceFull: return EDQUOT;
|
case BFile_DeviceFull: return EDQUOT;
|
||||||
case BFile_IllegalDevice: return EINVAL;
|
case BFile_IllegalDevice: return EINVAL;
|
||||||
case BFile_AccessDenied: return EACCES;
|
case BFile_AccessDenied: return EACCES;
|
||||||
case BFile_PermissionError: return EACCES;
|
case BFile_PermissionError: return EACCES;
|
||||||
case BFile_EntryFull: return EDQUOT;
|
case BFile_EntryFull: return EDQUOT;
|
||||||
case BFile_AlreadyExists: return EEXIST;
|
case BFile_AlreadyExists: return EEXIST;
|
||||||
case BFile_ReadOnlyFile: return EACCES;
|
case BFile_ReadOnlyFile: return EACCES;
|
||||||
case BFile_EnumerateEnd: return ENOENT;
|
case BFile_EnumerateEnd: return ENOENT;
|
||||||
case BFile_IllegalSeekPos: return EINVAL;
|
case BFile_IllegalSeekPos: return EINVAL;
|
||||||
case BFile_NotMountDevice: return ENOENT;
|
case BFile_NotMountDevice: return ENOENT;
|
||||||
case BFile_DeviceNotFound: return ENOENT;
|
case BFile_DeviceNotFound: return ENOENT;
|
||||||
default: return errno;
|
default: return errno;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,10 @@ int bfile_type_to_mode_t(int bfile_type)
|
||||||
return bfile_type == BFile_Type_Directory ? S_IFDIR : S_IFREG;
|
return bfile_type == BFile_Type_Directory ? S_IFDIR : S_IFREG;
|
||||||
#else
|
#else
|
||||||
switch(bfile_type) {
|
switch(bfile_type) {
|
||||||
case BFile_Type_Directory: return S_IFDIR;
|
case BFile_Type_Directory: return S_IFDIR;
|
||||||
case BFile_Type_Dot: return S_IFDIR;
|
case BFile_Type_Dot: return S_IFDIR;
|
||||||
case BFile_Type_DotDot: return S_IFDIR;
|
case BFile_Type_DotDot: return S_IFDIR;
|
||||||
default: return S_IFREG;
|
default: return S_IFREG;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -77,18 +77,18 @@ int bfile_type_to_dirent(int bfile_type)
|
||||||
return bfile_type == BFile_Type_Directory ? DT_DIR : DT_REG;
|
return bfile_type == BFile_Type_Directory ? DT_DIR : DT_REG;
|
||||||
#else
|
#else
|
||||||
switch(bfile_type) {
|
switch(bfile_type) {
|
||||||
case BFile_Type_Directory: return DT_DIR;
|
case BFile_Type_Directory: return DT_DIR;
|
||||||
case BFile_Type_Dot: return DT_DIR;
|
case BFile_Type_Dot: return DT_DIR;
|
||||||
case BFile_Type_DotDot: return DT_DIR;
|
case BFile_Type_DotDot: return DT_DIR;
|
||||||
case BFile_Type_MainMem: return DT_REG;
|
case BFile_Type_MainMem: return DT_REG;
|
||||||
case BFile_Type_File: return DT_REG;
|
case BFile_Type_File: return DT_REG;
|
||||||
case BFile_Type_Addin: return DT_REG;
|
case BFile_Type_Addin: return DT_REG;
|
||||||
case BFile_Type_Eact: return DT_REG;
|
case BFile_Type_Eact: return DT_REG;
|
||||||
case BFile_Type_Language: return DT_REG;
|
case BFile_Type_Language: return DT_REG;
|
||||||
case BFile_Type_Bitmap: return DT_REG;
|
case BFile_Type_Bitmap: return DT_REG;
|
||||||
case BFile_Type_Volume: return DT_BLK;
|
case BFile_Type_Volume: return DT_BLK;
|
||||||
case BFile_Type_Archived: return DT_REG;
|
case BFile_Type_Archived: return DT_REG;
|
||||||
default: return DT_UNKNOWN;
|
default: return DT_UNKNOWN;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,78 +10,78 @@
|
||||||
|
|
||||||
/* _fygue_fat16_cluster_get_next(): FAT16 cluster handling */
|
/* _fygue_fat16_cluster_get_next(): FAT16 cluster handling */
|
||||||
static int _fygue_fat16_cluster_get_next(
|
static int _fygue_fat16_cluster_get_next(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
int *cluster
|
int *cluster
|
||||||
) {
|
) {
|
||||||
uint16_t *fat0;
|
uint16_t *fat0;
|
||||||
int nb_entry_per_sector;
|
int nb_entry_per_sector;
|
||||||
int cluster_sector;
|
int cluster_sector;
|
||||||
int cluster_real;
|
int cluster_real;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
nb_entry_per_sector = fat->SectorSize / 2;
|
nb_entry_per_sector = fat->SectorSize / 2;
|
||||||
cluster_sector = *cluster / nb_entry_per_sector;
|
cluster_sector = *cluster / nb_entry_per_sector;
|
||||||
cluster_real = *cluster - (cluster_sector * nb_entry_per_sector);
|
cluster_real = *cluster - (cluster_sector * nb_entry_per_sector);
|
||||||
rc = fygue_fat_sector_get_addr(
|
rc = fygue_fat_sector_get_addr(
|
||||||
fat,
|
fat,
|
||||||
(void*)&fat0,
|
(void*)&fat0,
|
||||||
fat->FAT0SectorID + cluster_sector
|
fat->FAT0SectorID + cluster_sector
|
||||||
);
|
);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return -1;
|
return -1;
|
||||||
*cluster = FAT_WORD(fat0[cluster_real]);
|
*cluster = FAT_WORD(fat0[cluster_real]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_fat12_cluster_get_next(): FAT12 cluster handling */
|
/* _fygue_fat12_cluster_get_next(): FAT12 cluster handling */
|
||||||
// TODO: better calculus
|
// TODO: better calculus
|
||||||
static int _fygue_fat12_cluster_get_next(
|
static int _fygue_fat12_cluster_get_next(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
int *cluster
|
int *cluster
|
||||||
) {
|
) {
|
||||||
int fat_index0;
|
int fat_index0;
|
||||||
int fat_index1;
|
int fat_index1;
|
||||||
int fat_offset0;
|
int fat_offset0;
|
||||||
int fat_offset1;
|
int fat_offset1;
|
||||||
int fat_sector0;
|
int fat_sector0;
|
||||||
int fat_sector1;
|
int fat_sector1;
|
||||||
uintptr_t fat_data0;
|
uintptr_t fat_data0;
|
||||||
uintptr_t fat_data1;
|
uintptr_t fat_data1;
|
||||||
|
|
||||||
fat_index0 = *cluster + (*cluster / 2);
|
fat_index0 = *cluster + (*cluster / 2);
|
||||||
fat_index1 = fat_index0 + 1;
|
fat_index1 = fat_index0 + 1;
|
||||||
fat_sector0 = fat->FAT0SectorID + (fat_index0 / 512);
|
fat_sector0 = fat->FAT0SectorID + (fat_index0 / 512);
|
||||||
fat_sector1 = fat->FAT0SectorID + (fat_index1 / 512);
|
fat_sector1 = fat->FAT0SectorID + (fat_index1 / 512);
|
||||||
|
|
||||||
if (fat_sector0 == fat_sector1) {
|
if (fat_sector0 == fat_sector1) {
|
||||||
if (fygue_fat_sector_get_addr(fat, &fat_data0, fat_sector0) != 0)
|
if (fygue_fat_sector_get_addr(fat, &fat_data0, fat_sector0) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
fat_data1 = fat_data0;
|
fat_data1 = fat_data0;
|
||||||
fat_offset0 = fat_index0 - ((fat_index0 / 512) * 512);
|
fat_offset0 = fat_index0 - ((fat_index0 / 512) * 512);
|
||||||
fat_offset1 = fat_offset0 + 1;
|
fat_offset1 = fat_offset0 + 1;
|
||||||
} else {
|
} else {
|
||||||
if (fygue_fat_sector_get_addr(fat, &fat_data0, fat_sector0) != 0)
|
if (fygue_fat_sector_get_addr(fat, &fat_data0, fat_sector0) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (fygue_fat_sector_get_addr(fat, &fat_data1, fat_sector1) != 0)
|
if (fygue_fat_sector_get_addr(fat, &fat_data1, fat_sector1) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
fat_offset0 = fat_index0 - ((fat_index0 / 512) * 512);
|
fat_offset0 = fat_index0 - ((fat_index0 / 512) * 512);
|
||||||
fat_offset1 = fat_index1 - ((fat_index1 / 512) * 512);
|
fat_offset1 = fat_index1 - ((fat_index1 / 512) * 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*cluster & 1) {
|
if (*cluster & 1) {
|
||||||
*cluster = (
|
*cluster = (
|
||||||
(((((uint8_t*)fat_data0)[fat_offset0] & 0xf0) >> 4) << 0) |
|
(((((uint8_t*)fat_data0)[fat_offset0] & 0xf0) >> 4) << 0) |
|
||||||
(((((uint8_t*)fat_data1)[fat_offset1] & 0xff) >> 0) << 4)
|
(((((uint8_t*)fat_data1)[fat_offset1] & 0xff) >> 0) << 4)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
*cluster = (
|
*cluster = (
|
||||||
(((((uint8_t*)fat_data0)[fat_offset0] & 0xff) >> 0) << 0) |
|
(((((uint8_t*)fat_data0)[fat_offset0] & 0xff) >> 0) << 0) |
|
||||||
(((((uint8_t*)fat_data1)[fat_offset1] & 0x0f) >> 0) << 8)
|
(((((uint8_t*)fat_data1)[fat_offset1] & 0x0f) >> 0) << 8)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (*cluster == 0x0fff)
|
if (*cluster == 0x0fff)
|
||||||
*cluster = 0xffff;
|
*cluster = 0xffff;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -104,61 +104,61 @@ static int _fygue_fat12_cluster_get_next(
|
||||||
* - ensure FAT1 information is the same ? */
|
* - ensure FAT1 information is the same ? */
|
||||||
int fygue_fat_cluster_get_next(struct fygue_fat *fat, int *cluster_current)
|
int fygue_fat_cluster_get_next(struct fygue_fat *fat, int *cluster_current)
|
||||||
{
|
{
|
||||||
int cluster;
|
int cluster;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fat == NULL || cluster_current == NULL)
|
if (fat == NULL || cluster_current == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
cluster = *cluster_current;
|
cluster = *cluster_current;
|
||||||
if (cluster == 0xffff)
|
if (cluster == 0xffff)
|
||||||
return -3;
|
return -3;
|
||||||
if (cluster == 0x0000)
|
if (cluster == 0x0000)
|
||||||
return -4;
|
return -4;
|
||||||
if (cluster <= 1)
|
if (cluster <= 1)
|
||||||
return -2;
|
return -2;
|
||||||
if (cluster >= fat->ClusterCount)
|
if (cluster >= fat->ClusterCount)
|
||||||
return -2;
|
return -2;
|
||||||
if (fat->Type == FYGUE_FAT_TYPE_FAT12)
|
if (fat->Type == FYGUE_FAT_TYPE_FAT12)
|
||||||
rc = _fygue_fat12_cluster_get_next(fat, &cluster);
|
rc = _fygue_fat12_cluster_get_next(fat, &cluster);
|
||||||
if (fat->Type == FYGUE_FAT_TYPE_FAT16)
|
if (fat->Type == FYGUE_FAT_TYPE_FAT16)
|
||||||
rc = _fygue_fat16_cluster_get_next(fat, &cluster);
|
rc = _fygue_fat16_cluster_get_next(fat, &cluster);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -5;
|
return -5;
|
||||||
if (cluster == 0xffff)
|
if (cluster == 0xffff)
|
||||||
rc = -6;
|
rc = -6;
|
||||||
if (cluster == 0x0000)
|
if (cluster == 0x0000)
|
||||||
rc = -7;
|
rc = -7;
|
||||||
*cluster_current = cluster;
|
*cluster_current = cluster;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_fat_cluster_get_sector() - get sector ID from cluster ID */
|
/* fygue_fat_cluster_get_sector() - get sector ID from cluster ID */
|
||||||
int fygue_fat_cluster_get_sector(
|
int fygue_fat_cluster_get_sector(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
int cluster_id,
|
int cluster_id,
|
||||||
int *sector_id
|
int *sector_id
|
||||||
) {
|
) {
|
||||||
if (fat == NULL || sector_id == NULL)
|
if (fat == NULL || sector_id == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (cluster_id >= fat->ClusterCount)
|
if (cluster_id >= fat->ClusterCount)
|
||||||
return -1;
|
return -1;
|
||||||
if (cluster_id <= 1) {
|
if (cluster_id <= 1) {
|
||||||
*sector_id = fat->RootSectorID;
|
*sector_id = fat->RootSectorID;
|
||||||
} else {
|
} else {
|
||||||
*sector_id = fat->DataSectorID + ((cluster_id - 2) * 8);
|
*sector_id = fat->DataSectorID + ((cluster_id - 2) * 8);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_fat_get_cluster_addr() - get logical sector addr */
|
/* fygue_fat_get_cluster_addr() - get logical sector addr */
|
||||||
int fygue_fat_cluster_get_addr(
|
int fygue_fat_cluster_get_addr(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
uintptr_t *addr,
|
uintptr_t *addr,
|
||||||
int cluster_id
|
int cluster_id
|
||||||
) {
|
) {
|
||||||
int sector_id;
|
int sector_id;
|
||||||
|
|
||||||
if (fygue_fat_cluster_get_sector(fat, cluster_id, §or_id) != 0)
|
if (fygue_fat_cluster_get_sector(fat, cluster_id, §or_id) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
return fygue_fat_sector_get_addr(fat, addr, sector_id);
|
return fygue_fat_sector_get_addr(fat, addr, sector_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** fygue/fat/initialize - FAT initialization
|
** fygue/fat/initialize - FAT initialization
|
||||||
*/
|
*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -15,35 +15,35 @@
|
||||||
/* struct _fat_bpb : Bios Parameter Block */
|
/* struct _fat_bpb : Bios Parameter Block */
|
||||||
struct _fat_bpb
|
struct _fat_bpb
|
||||||
{
|
{
|
||||||
// common boot structure
|
// common boot structure
|
||||||
uint8_t BS_jmpBoot[3];
|
uint8_t BS_jmpBoot[3];
|
||||||
uint8_t BS_OEMName[8];
|
uint8_t BS_OEMName[8];
|
||||||
|
|
||||||
// BIOS parameter Block
|
// BIOS parameter Block
|
||||||
uint16_t BPB_BytsPerSec;
|
uint16_t BPB_BytsPerSec;
|
||||||
uint8_t BPB_SecPerClus;
|
uint8_t BPB_SecPerClus;
|
||||||
uint16_t BPB_RsvdSecCnt;
|
uint16_t BPB_RsvdSecCnt;
|
||||||
uint8_t BPB_NumFATs;
|
uint8_t BPB_NumFATs;
|
||||||
uint16_t BPB_RootEntCnt;
|
uint16_t BPB_RootEntCnt;
|
||||||
uint16_t BPB_TotSec16;
|
uint16_t BPB_TotSec16;
|
||||||
uint8_t BPB_Media;
|
uint8_t BPB_Media;
|
||||||
uint16_t BPB_FATSz16;
|
uint16_t BPB_FATSz16;
|
||||||
uint16_t BPB_SecPerTrk;
|
uint16_t BPB_SecPerTrk;
|
||||||
uint16_t BPB_NumHeads;
|
uint16_t BPB_NumHeads;
|
||||||
uint32_t BPB_HiddSec;
|
uint32_t BPB_HiddSec;
|
||||||
uint32_t BPB_TotSec32;
|
uint32_t BPB_TotSec32;
|
||||||
|
|
||||||
// Extended BIOS Parameter Block
|
// Extended BIOS Parameter Block
|
||||||
uint8_t BS_DrvNum;
|
uint8_t BS_DrvNum;
|
||||||
uint8_t BS_Reserved1;
|
uint8_t BS_Reserved1;
|
||||||
uint8_t BS_BootSig;
|
uint8_t BS_BootSig;
|
||||||
uint8_t BS_VolID[4];
|
uint8_t BS_VolID[4];
|
||||||
uint8_t BS_VolLab[11];
|
uint8_t BS_VolLab[11];
|
||||||
uint8_t BS_FilSysType[8];
|
uint8_t BS_FilSysType[8];
|
||||||
uint8_t _unused[448];
|
uint8_t _unused[448];
|
||||||
|
|
||||||
// Signature
|
// Signature
|
||||||
uint8_t Signature_word[2];
|
uint8_t Signature_word[2];
|
||||||
} GPACKED(1);
|
} GPACKED(1);
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,35 +55,35 @@ struct _fat_bpb
|
||||||
* on fecthed information, Fugue select an hardcoded FAT configuration
|
* on fecthed information, Fugue select an hardcoded FAT configuration
|
||||||
*
|
*
|
||||||
* return
|
* return
|
||||||
* -1 unable to load the sector0
|
* -1 unable to load the sector0
|
||||||
* -2 unsupported Fugue configuration */
|
* -2 unsupported Fugue configuration */
|
||||||
static int _fygue_fat_sector0(struct fygue_fat *fat)
|
static int _fygue_fat_sector0(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
uint8_t *sector;
|
uint8_t *sector;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fygue_fat_sector_get_addr(fat, (void*)§or, 0) != 0)
|
if (fygue_fat_sector_get_addr(fat, (void*)§or, 0) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
fat->SectorHiddenCount = (
|
fat->SectorHiddenCount = (
|
||||||
(sector[0x1c9] << 24) |
|
(sector[0x1c9] << 24) |
|
||||||
(sector[0x1c8] << 16) |
|
(sector[0x1c8] << 16) |
|
||||||
(sector[0x1c7] << 8) |
|
(sector[0x1c7] << 8) |
|
||||||
(sector[0x1c6] << 0)
|
(sector[0x1c6] << 0)
|
||||||
);
|
);
|
||||||
fat->SectorCount = (
|
fat->SectorCount = (
|
||||||
(sector[0x1cd] << 24) |
|
(sector[0x1cd] << 24) |
|
||||||
(sector[0x1cc] << 16) |
|
(sector[0x1cc] << 16) |
|
||||||
(sector[0x1cb] << 8) |
|
(sector[0x1cb] << 8) |
|
||||||
(sector[0x1ca] << 0)
|
(sector[0x1ca] << 0)
|
||||||
);
|
);
|
||||||
rc = fygue_fat_sector_get_addr(
|
rc = fygue_fat_sector_get_addr(
|
||||||
fat,
|
fat,
|
||||||
&fat->BPB,
|
&fat->BPB,
|
||||||
fat->SectorHiddenCount
|
fat->SectorHiddenCount
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -2;
|
return -2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_fat_configure() - configure the FAT information
|
/* _fygue_fat_configure() - configure the FAT information
|
||||||
|
@ -97,56 +97,56 @@ static int _fygue_fat_sector0(struct fygue_fat *fat)
|
||||||
* FAT */
|
* FAT */
|
||||||
static int _fygue_fat_configure(struct fygue_fat *fat)
|
static int _fygue_fat_configure(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
struct _fat_bpb *bpb;
|
struct _fat_bpb *bpb;
|
||||||
int RootDirSectors;
|
int RootDirSectors;
|
||||||
int DataSec;
|
int DataSec;
|
||||||
|
|
||||||
bpb = (void *)fat->BPB;
|
bpb = (void *)fat->BPB;
|
||||||
|
|
||||||
RootDirSectors = FAT_WORD(bpb->BPB_RootEntCnt) * 32;
|
RootDirSectors = FAT_WORD(bpb->BPB_RootEntCnt) * 32;
|
||||||
RootDirSectors += FAT_WORD(bpb->BPB_BytsPerSec) - 1;
|
RootDirSectors += FAT_WORD(bpb->BPB_BytsPerSec) - 1;
|
||||||
RootDirSectors /= FAT_WORD(bpb->BPB_BytsPerSec);
|
RootDirSectors /= FAT_WORD(bpb->BPB_BytsPerSec);
|
||||||
DataSec = FAT_WORD(bpb->BPB_RsvdSecCnt);
|
DataSec = FAT_WORD(bpb->BPB_RsvdSecCnt);
|
||||||
DataSec += FAT_WORD(bpb->BPB_FATSz16) * bpb->BPB_NumFATs;
|
DataSec += FAT_WORD(bpb->BPB_FATSz16) * bpb->BPB_NumFATs;
|
||||||
DataSec += RootDirSectors;
|
DataSec += RootDirSectors;
|
||||||
DataSec = FAT_WORD(bpb->BPB_TotSec16) - DataSec;
|
DataSec = FAT_WORD(bpb->BPB_TotSec16) - DataSec;
|
||||||
fat->ClusterCount = DataSec / bpb->BPB_SecPerClus;
|
fat->ClusterCount = DataSec / bpb->BPB_SecPerClus;
|
||||||
if (fat->ClusterCount < 4085) {
|
if (fat->ClusterCount < 4085) {
|
||||||
fat->Type = FYGUE_FAT_TYPE_FAT12;
|
fat->Type = FYGUE_FAT_TYPE_FAT12;
|
||||||
} else if (fat->ClusterCount < 65525) {
|
} else if (fat->ClusterCount < 65525) {
|
||||||
fat->Type = FYGUE_FAT_TYPE_FAT16;
|
fat->Type = FYGUE_FAT_TYPE_FAT16;
|
||||||
} else {
|
} else {
|
||||||
// TODO: (FAT32) maybe gint panic ?
|
// TODO: (FAT32) maybe gint panic ?
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
fat->TotalCapacity = DataSec * FAT_WORD(bpb->BPB_BytsPerSec);
|
fat->TotalCapacity = DataSec * FAT_WORD(bpb->BPB_BytsPerSec);
|
||||||
fat->RootEntCount = FAT_WORD(bpb->BPB_RootEntCnt);
|
fat->RootEntCount = FAT_WORD(bpb->BPB_RootEntCnt);
|
||||||
fat->SectorSize = FAT_WORD(bpb->BPB_BytsPerSec);
|
fat->SectorSize = FAT_WORD(bpb->BPB_BytsPerSec);
|
||||||
fat->SectorPerClus = bpb->BPB_SecPerClus;
|
fat->SectorPerClus = bpb->BPB_SecPerClus;
|
||||||
|
|
||||||
fat->FAT0SectorID = fat->SectorHiddenCount;
|
fat->FAT0SectorID = fat->SectorHiddenCount;
|
||||||
fat->FAT0SectorID += FAT_WORD(bpb->BPB_RsvdSecCnt);
|
fat->FAT0SectorID += FAT_WORD(bpb->BPB_RsvdSecCnt);
|
||||||
fat->FAT1SectorID = fat->FAT0SectorID;
|
fat->FAT1SectorID = fat->FAT0SectorID;
|
||||||
fat->FAT1SectorID += FAT_WORD(bpb->BPB_FATSz16);
|
fat->FAT1SectorID += FAT_WORD(bpb->BPB_FATSz16);
|
||||||
fat->RootSectorID = fat->FAT1SectorID;
|
fat->RootSectorID = fat->FAT1SectorID;
|
||||||
fat->RootSectorID += FAT_WORD(bpb->BPB_FATSz16);
|
fat->RootSectorID += FAT_WORD(bpb->BPB_FATSz16);
|
||||||
fat->DataSectorID = fat->RootSectorID;
|
fat->DataSectorID = fat->RootSectorID;
|
||||||
fat->DataSectorID += RootDirSectors;
|
fat->DataSectorID += RootDirSectors;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_fat_prepare() - prepare logic information */
|
/* _fygue_fat_prepare() - prepare logic information */
|
||||||
static int _fygue_fat_prepare(struct fygue_fat *fat)
|
static int _fygue_fat_prepare(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
int rc = fygue_fat_sector_get_addr(
|
int rc = fygue_fat_sector_get_addr(
|
||||||
fat,
|
fat,
|
||||||
&fat->RootAddr,
|
&fat->RootAddr,
|
||||||
fat->RootSectorID
|
fat->RootSectorID
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -156,28 +156,28 @@ static int _fygue_fat_prepare(struct fygue_fat *fat)
|
||||||
/* fygue_fat_initialize() - fully initialize the FAT information */
|
/* fygue_fat_initialize() - fully initialize the FAT information */
|
||||||
int fygue_fat_initialize(struct fygue_fat *fat)
|
int fygue_fat_initialize(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
if (fat == NULL)
|
if (fat == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
memset(fat, 0x00, sizeof(struct fygue_fat));
|
memset(fat, 0x00, sizeof(struct fygue_fat));
|
||||||
if (fygue_flash_initialize(&(fat->_flash)) != 0)
|
if (fygue_flash_initialize(&(fat->_flash)) != 0)
|
||||||
return -2;
|
return -2;
|
||||||
if (_fygue_fat_sector0(fat) != 0)
|
if (_fygue_fat_sector0(fat) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
if (_fygue_fat_configure(fat) != 0)
|
if (_fygue_fat_configure(fat) != 0)
|
||||||
return -4;
|
return -4;
|
||||||
if (_fygue_fat_prepare(fat) != 0)
|
if (_fygue_fat_prepare(fat) != 0)
|
||||||
return -5;
|
return -5;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_fat_sync(): re-initialize the FAT information */
|
/* fygue_fat_sync(): re-initialize the FAT information */
|
||||||
int fygue_fat_sync(struct fygue_fat *fat)
|
int fygue_fat_sync(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
if (fat == NULL)
|
if (fat == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (fygue_flash_sync((&fat->_flash)) != 0)
|
if (fygue_flash_sync((&fat->_flash)) != 0)
|
||||||
return -2;
|
return -2;
|
||||||
if (_fygue_fat_prepare(fat) != 0)
|
if (_fygue_fat_prepare(fat) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,21 +8,21 @@
|
||||||
|
|
||||||
/* _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) \
|
||||||
| (((x) & 0x000000ff) << 24) \
|
| (((x) & 0x000000ff) << 24) \
|
||||||
)
|
)
|
||||||
|
|
||||||
/* FYGUE_FAT_ATTR_* : FAT dirent attribute */
|
/* FYGUE_FAT_ATTR_* : FAT dirent attribute */
|
||||||
#define FYGUE_FAT_ATTR_READ_ONLY 0x01
|
#define FYGUE_FAT_ATTR_READ_ONLY 0x01
|
||||||
#define FYGUE_FAT_ATTR_HIDDEN 0x02
|
#define FYGUE_FAT_ATTR_HIDDEN 0x02
|
||||||
#define FYGUE_FAT_ATTR_SYSTEM 0x04
|
#define FYGUE_FAT_ATTR_SYSTEM 0x04
|
||||||
#define FYGUE_FAT_ATTR_VOLUME 0x08
|
#define FYGUE_FAT_ATTR_VOLUME 0x08
|
||||||
#define FYGUE_FAT_ATTR_DIRECTORY 0x10
|
#define FYGUE_FAT_ATTR_DIRECTORY 0x10
|
||||||
#define FYGUE_FAT_ATTR_ARCHIVE 0x20
|
#define FYGUE_FAT_ATTR_ARCHIVE 0x20
|
||||||
|
|
||||||
|
@ -30,81 +30,81 @@
|
||||||
// TODO: rename fields
|
// TODO: rename fields
|
||||||
struct fygue_fat
|
struct fygue_fat
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
FYGUE_FAT_TYPE_FAT12 = 0,
|
FYGUE_FAT_TYPE_FAT12 = 0,
|
||||||
FYGUE_FAT_TYPE_FAT16 = 1,
|
FYGUE_FAT_TYPE_FAT16 = 1,
|
||||||
} Type;
|
} Type;
|
||||||
int SectorHiddenCount;
|
int SectorHiddenCount;
|
||||||
int SectorCount;
|
int SectorCount;
|
||||||
int SectorSize;
|
int SectorSize;
|
||||||
int SectorPerClus;
|
int SectorPerClus;
|
||||||
int ClusterCount;
|
int ClusterCount;
|
||||||
int TotalCapacity;
|
int TotalCapacity;
|
||||||
int RootEntCount;
|
int RootEntCount;
|
||||||
int FAT0SectorID;
|
int FAT0SectorID;
|
||||||
int FAT1SectorID;
|
int FAT1SectorID;
|
||||||
int RootSectorID;
|
int RootSectorID;
|
||||||
int DataSectorID;
|
int DataSectorID;
|
||||||
uintptr_t RootAddr;
|
uintptr_t RootAddr;
|
||||||
uintptr_t BPB;
|
uintptr_t BPB;
|
||||||
struct fygue_flash _flash;
|
struct fygue_flash _flash;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_fat_dirent - FAT dirent information */
|
/* fygue_fat_dirent - FAT dirent information */
|
||||||
//TODO: flexible name array like the high-level `struct dirent` ?
|
//TODO: flexible name array like the high-level `struct dirent` ?
|
||||||
struct fygue_fat_dirent
|
struct fygue_fat_dirent
|
||||||
{
|
{
|
||||||
char name[256];
|
char name[256];
|
||||||
size_t size;
|
size_t size;
|
||||||
uintptr_t meta_addr;
|
uintptr_t meta_addr;
|
||||||
unsigned int cluster_id;
|
unsigned int cluster_id;
|
||||||
int attribute;
|
int attribute;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_fat_dir - fygue directory information */
|
/* fygue_fat_dir - fygue directory information */
|
||||||
struct fygue_fat_dir
|
struct fygue_fat_dir
|
||||||
{
|
{
|
||||||
int cluster_entry;
|
int cluster_entry;
|
||||||
int cluster_current;
|
int cluster_current;
|
||||||
int root_dirent_count;
|
int root_dirent_count;
|
||||||
int sector_id;
|
int sector_id;
|
||||||
int sector_count;
|
int sector_count;
|
||||||
int dirent_cursor;
|
int dirent_cursor;
|
||||||
uintptr_t dirent_current_addr;
|
uintptr_t dirent_current_addr;
|
||||||
bool end_of_dirent;
|
bool end_of_dirent;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
int attribute;
|
int attribute;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_fat_file: file information needed to perform IO primitives */
|
/* fygue_fat_file: file information needed to perform IO primitives */
|
||||||
struct fygue_fat_file
|
struct fygue_fat_file
|
||||||
{
|
{
|
||||||
int cluster_entry;
|
int cluster_entry;
|
||||||
int attribute;
|
int attribute;
|
||||||
size_t size;
|
size_t size;
|
||||||
off_t cursor;
|
off_t cursor;
|
||||||
struct {
|
struct {
|
||||||
uintptr_t addr;
|
uintptr_t addr;
|
||||||
size_t size;
|
size_t size;
|
||||||
int cluster_count;
|
int cluster_count;
|
||||||
} *chunk;
|
} *chunk;
|
||||||
int chunk_table_max_index;
|
int chunk_table_max_index;
|
||||||
int chunk_count;
|
int chunk_count;
|
||||||
int chunk_rd_index;
|
int chunk_rd_index;
|
||||||
int chunk_rd_offset;
|
int chunk_rd_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_fat_descriptor: FAT descriptor information */
|
/* fygue_fat_descriptor: FAT descriptor information */
|
||||||
struct fygue_fat_descriptor
|
struct fygue_fat_descriptor
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
FYGUE_FAT_DESC_TYPE_FILE,
|
FYGUE_FAT_DESC_TYPE_FILE,
|
||||||
FYGUE_FAT_DESC_TYPE_DIR,
|
FYGUE_FAT_DESC_TYPE_DIR,
|
||||||
} type;
|
} type;
|
||||||
union {
|
union {
|
||||||
struct fygue_fat_file file;
|
struct fygue_fat_file file;
|
||||||
struct fygue_fat_dir dir;
|
struct fygue_fat_dir dir;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -119,9 +119,9 @@ extern int fygue_fat_sync(struct fygue_fat *fat);
|
||||||
|
|
||||||
/* fygue_fat_open() - resolve the path and set the dirent information */
|
/* fygue_fat_open() - resolve the path and set the dirent information */
|
||||||
extern int fygue_fat_open(
|
extern int fygue_fat_open(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_fat_descriptor *desc
|
struct fygue_fat_descriptor *desc
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -130,36 +130,36 @@ extern int fygue_fat_open(
|
||||||
|
|
||||||
/* fugue_fat_dir_open(): convert dirent to dir */
|
/* fugue_fat_dir_open(): convert dirent to dir */
|
||||||
extern int fygue_fat_dir_open(
|
extern int fygue_fat_dir_open(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct fygue_fat_dirent *dirent
|
struct fygue_fat_dirent *dirent
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_dir_read(): readdir primitive */
|
/* fygue_fat_dir_read(): readdir primitive */
|
||||||
extern int fygue_fat_dir_read(
|
extern int fygue_fat_dir_read(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct fygue_fat_dirent *dirent
|
struct fygue_fat_dirent *dirent
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_dir_close(): closedir primitive */
|
/* fygue_fat_dir_close(): closedir primitive */
|
||||||
extern int fygue_fat_dir_close(
|
extern int fygue_fat_dir_close(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir
|
struct fygue_fat_dir *dir
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_dir_stat(): directory stat primitive */
|
/* fygue_fat_dir_stat(): directory stat primitive */
|
||||||
extern int fygue_fat_dir_stat(
|
extern int fygue_fat_dir_stat(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct stat *statbuf
|
struct stat *statbuf
|
||||||
);
|
);
|
||||||
|
|
||||||
/* 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
|
int cluster_id
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -168,44 +168,44 @@ extern int fygue_fat_dir_sync(
|
||||||
|
|
||||||
/* _fygue_fat_file_open(): generate file information */
|
/* _fygue_fat_file_open(): generate file information */
|
||||||
extern int fygue_fat_file_open(
|
extern int fygue_fat_file_open(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
struct fygue_fat_dirent *dirent
|
struct fygue_fat_dirent *dirent
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_file_read(): read primitive */
|
/* fygue_fat_file_read(): read primitive */
|
||||||
extern int fygue_fat_file_read(
|
extern int fygue_fat_file_read(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_file_stat(): stat primitive */
|
/* fygue_fat_file_stat(): stat primitive */
|
||||||
extern int fygue_fat_file_stat(
|
extern int fygue_fat_file_stat(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
struct stat *statbuf
|
struct stat *statbuf
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_file_seek(): lseek primitive */
|
/* fygue_fat_file_seek(): lseek primitive */
|
||||||
extern int fygue_fat_file_seek(
|
extern int fygue_fat_file_seek(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
off_t offset
|
off_t offset
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_file_close(): close primitive */
|
/* fygue_fat_file_close(): close primitive */
|
||||||
extern int fygue_fat_file_close(
|
extern int fygue_fat_file_close(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file
|
struct fygue_fat_file *file
|
||||||
);
|
);
|
||||||
|
|
||||||
/* 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
|
int cluster_id
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -214,22 +214,22 @@ extern int fygue_fat_file_sync(
|
||||||
|
|
||||||
/* fygue_fat_cluster_get_next() - find the next cluster ID of a file */
|
/* fygue_fat_cluster_get_next() - find the next cluster ID of a file */
|
||||||
extern int fygue_fat_cluster_get_next(
|
extern int fygue_fat_cluster_get_next(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
int *cluster_current
|
int *cluster_current
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_cluster_get_sector() - get sector ID from cluster ID */
|
/* fygue_fat_cluster_get_sector() - get sector ID from cluster ID */
|
||||||
extern int fygue_fat_cluster_get_sector(
|
extern int fygue_fat_cluster_get_sector(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
int cluster_id,
|
int cluster_id,
|
||||||
int *sector_id
|
int *sector_id
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_fat_get_cluster_addr() - get logical sector addr */
|
/* fygue_fat_get_cluster_addr() - get logical sector addr */
|
||||||
extern int fygue_fat_cluster_get_addr(
|
extern int fygue_fat_cluster_get_addr(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
uintptr_t *addr,
|
uintptr_t *addr,
|
||||||
int cluster_id
|
int cluster_id
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -238,9 +238,9 @@ extern int fygue_fat_cluster_get_addr(
|
||||||
|
|
||||||
/* fygue_fat_get_sector_addr() - get logical sector addr */
|
/* fygue_fat_get_sector_addr() - get logical sector addr */
|
||||||
extern int fygue_fat_sector_get_addr(
|
extern int fygue_fat_sector_get_addr(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
uintptr_t *addr,
|
uintptr_t *addr,
|
||||||
int sector
|
int sector
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif /* FS_FYGUE_FAT_H */
|
#endif /* FS_FYGUE_FAT_H */
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
/* fygue_fat_dir_close(): closedir primitive */
|
/* fygue_fat_dir_close(): closedir primitive */
|
||||||
int fygue_fat_dir_close(struct fygue_fat *fat, struct fygue_fat_dir *dir)
|
int fygue_fat_dir_close(struct fygue_fat *fat, struct fygue_fat_dir *dir)
|
||||||
{
|
{
|
||||||
if (fat == NULL || dir == NULL)
|
if (fat == NULL || dir == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
// nothing to do here...
|
// nothing to do here...
|
||||||
memset(dir, 0x00, sizeof(struct fygue_fat_file));
|
memset(dir, 0x00, sizeof(struct fygue_fat_file));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,21 +3,21 @@
|
||||||
|
|
||||||
/* fugue_fat_dir_open(): convert dirent to dir */
|
/* fugue_fat_dir_open(): convert dirent to dir */
|
||||||
int fygue_fat_dir_open(
|
int fygue_fat_dir_open(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct fygue_fat_dirent *dirent
|
struct fygue_fat_dirent *dirent
|
||||||
) {
|
) {
|
||||||
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_DESC_TYPE_DIR;
|
dir->attribute = FYGUE_FAT_DESC_TYPE_DIR;
|
||||||
} else {
|
} else {
|
||||||
if ((dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY) == 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_DESC_TYPE_DIR;
|
dir->attribute = FYGUE_FAT_DESC_TYPE_DIR;
|
||||||
dir->root_dirent_count = 0;
|
dir->root_dirent_count = 0;
|
||||||
}
|
}
|
||||||
return fygue_fat_dir_sync(fat, dir, dir->cluster_entry);
|
return fygue_fat_dir_sync(fat, dir, dir->cluster_entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,56 +16,56 @@
|
||||||
/* _fat_dirent - FAT directory entry structure */
|
/* _fat_dirent - FAT directory entry structure */
|
||||||
struct _fat_dirent
|
struct _fat_dirent
|
||||||
{
|
{
|
||||||
uint8_t DIR_Name[11];
|
uint8_t DIR_Name[11];
|
||||||
uint8_t DIR_Attr;
|
uint8_t DIR_Attr;
|
||||||
uint8_t DIR_NTRes;
|
uint8_t DIR_NTRes;
|
||||||
uint8_t DIR_CrtTimeTenth;
|
uint8_t DIR_CrtTimeTenth;
|
||||||
uint16_t DIR_CrtTime;
|
uint16_t DIR_CrtTime;
|
||||||
uint16_t DIR_CrtDate;
|
uint16_t DIR_CrtDate;
|
||||||
uint16_t DIR_LstAccDate;
|
uint16_t DIR_LstAccDate;
|
||||||
uint16_t DIR_FstClusHI;
|
uint16_t DIR_FstClusHI;
|
||||||
uint16_t DIR_WrtTime;
|
uint16_t DIR_WrtTime;
|
||||||
uint16_t DIR_WrtDate;
|
uint16_t DIR_WrtDate;
|
||||||
uint16_t DIR_FstClusLO;
|
uint16_t DIR_FstClusLO;
|
||||||
uint32_t DIR_FileSize;
|
uint32_t DIR_FileSize;
|
||||||
} GPACKED(1);
|
} GPACKED(1);
|
||||||
|
|
||||||
/* _fat_dir_name : Fugue directory name strcuture */
|
/* _fat_dir_name : Fugue directory name strcuture */
|
||||||
struct _fat_dirname
|
struct _fat_dirname
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
uint8_t :1; // must be 0
|
uint8_t :1; // must be 0
|
||||||
uint8_t last :1;
|
uint8_t last :1;
|
||||||
uint8_t :1; // must be 0
|
uint8_t :1; // must be 0
|
||||||
uint8_t id :5;
|
uint8_t id :5;
|
||||||
} DIR_Sequence;
|
} DIR_Sequence;
|
||||||
uint16_t DIR_Char0;
|
uint16_t DIR_Char0;
|
||||||
uint16_t DIR_Char1;
|
uint16_t DIR_Char1;
|
||||||
uint16_t DIR_Char2;
|
uint16_t DIR_Char2;
|
||||||
uint16_t DIR_Char3;
|
uint16_t DIR_Char3;
|
||||||
uint16_t DIR_Char4;
|
uint16_t DIR_Char4;
|
||||||
uint8_t DIR_Attr; // must be 0x0f
|
uint8_t DIR_Attr; // must be 0x0f
|
||||||
uint8_t DIR_Type; // must be 0x00
|
uint8_t DIR_Type; // must be 0x00
|
||||||
uint8_t checksum;
|
uint8_t checksum;
|
||||||
uint16_t DIR_Char5;
|
uint16_t DIR_Char5;
|
||||||
uint16_t DIR_Char6;
|
uint16_t DIR_Char6;
|
||||||
uint16_t DIR_Char7;
|
uint16_t DIR_Char7;
|
||||||
uint16_t DIR_Char8;
|
uint16_t DIR_Char8;
|
||||||
uint16_t DIR_Char9;
|
uint16_t DIR_Char9;
|
||||||
uint16_t DIR_Char10;
|
uint16_t DIR_Char10;
|
||||||
uint16_t DIR_FstClus; // must be 0x0000
|
uint16_t DIR_FstClus; // must be 0x0000
|
||||||
uint16_t DIR_Char11;
|
uint16_t DIR_Char11;
|
||||||
uint16_t DIR_Char12;
|
uint16_t DIR_Char12;
|
||||||
} GPACKED(1);
|
} GPACKED(1);
|
||||||
|
|
||||||
/* _fat_info - internal struct info */
|
/* _fat_info - internal struct info */
|
||||||
struct _fat_info
|
struct _fat_info
|
||||||
{
|
{
|
||||||
struct fygue_fat *fat;
|
struct fygue_fat *fat;
|
||||||
struct fygue_fat_dir *dir;
|
struct fygue_fat_dir *dir;
|
||||||
struct fygue_fat_dirent *current;
|
struct fygue_fat_dirent *current;
|
||||||
uint8_t *filename;
|
uint8_t *filename;
|
||||||
int idx;
|
int idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,66 +76,66 @@ struct _fat_info
|
||||||
* - special root handling (root= dir->cluster_id == 0)
|
* - special root handling (root= dir->cluster_id == 0)
|
||||||
*
|
*
|
||||||
* return
|
* return
|
||||||
* -1 end of dirent
|
* -1 end of dirent
|
||||||
* 0 success */
|
* 0 success */
|
||||||
static int _fygue_fat_readdir_cursor_update(struct _fat_info *finfo)
|
static int _fygue_fat_readdir_cursor_update(struct _fat_info *finfo)
|
||||||
{
|
{
|
||||||
struct fygue_fat_dir *dir;
|
struct fygue_fat_dir *dir;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
dir = finfo->dir;
|
dir = finfo->dir;
|
||||||
if (dir->end_of_dirent == true)
|
if (dir->end_of_dirent == true)
|
||||||
return -1;
|
return -1;
|
||||||
dir->end_of_dirent = true;
|
dir->end_of_dirent = true;
|
||||||
if (dir->cluster_entry == 0)
|
if (dir->cluster_entry == 0)
|
||||||
{
|
{
|
||||||
dir->dirent_cursor += 1;
|
dir->dirent_cursor += 1;
|
||||||
if (dir->dirent_cursor >= dir->root_dirent_count)
|
if (dir->dirent_cursor >= dir->root_dirent_count)
|
||||||
return -1;
|
return -1;
|
||||||
if ((dir->dirent_cursor % 16) != 0)
|
if ((dir->dirent_cursor % 16) != 0)
|
||||||
{
|
{
|
||||||
dir->dirent_current_addr += sizeof(struct _fat_dirent);
|
dir->dirent_current_addr += sizeof(struct _fat_dirent);
|
||||||
dir->end_of_dirent = false;
|
dir->end_of_dirent = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dir->sector_id += 1;
|
dir->sector_id += 1;
|
||||||
} else {
|
} else {
|
||||||
dir->dirent_cursor += 1;
|
dir->dirent_cursor += 1;
|
||||||
if ((dir->dirent_cursor % 16) != 0)
|
if ((dir->dirent_cursor % 16) != 0)
|
||||||
{
|
{
|
||||||
dir->dirent_current_addr += sizeof(struct _fat_dirent);
|
dir->dirent_current_addr += sizeof(struct _fat_dirent);
|
||||||
dir->end_of_dirent = false;
|
dir->end_of_dirent = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dir->dirent_cursor = 0;
|
dir->dirent_cursor = 0;
|
||||||
dir->sector_count += 1;
|
dir->sector_count += 1;
|
||||||
if (dir->sector_count >= 8)
|
if (dir->sector_count >= 8)
|
||||||
{
|
{
|
||||||
rc = fygue_fat_cluster_get_next(
|
rc = fygue_fat_cluster_get_next(
|
||||||
finfo->fat,
|
finfo->fat,
|
||||||
&dir->cluster_current
|
&dir->cluster_current
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
rc = fygue_fat_cluster_get_sector(
|
rc = fygue_fat_cluster_get_sector(
|
||||||
finfo->fat,
|
finfo->fat,
|
||||||
dir->cluster_current,
|
dir->cluster_current,
|
||||||
&dir->sector_id
|
&dir->sector_id
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
dir->sector_count = 0;
|
dir->sector_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = fygue_fat_sector_get_addr(
|
rc = fygue_fat_sector_get_addr(
|
||||||
finfo->fat,
|
finfo->fat,
|
||||||
&dir->dirent_current_addr,
|
&dir->dirent_current_addr,
|
||||||
dir->sector_id
|
dir->sector_id
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
dir->end_of_dirent = false;
|
dir->end_of_dirent = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -144,114 +144,114 @@ static int _fygue_fat_readdir_cursor_update(struct _fat_info *finfo)
|
||||||
|
|
||||||
/* _fygue_fat_readdir_dirent_gen() - generate dirent */
|
/* _fygue_fat_readdir_dirent_gen() - generate dirent */
|
||||||
static void _fygue_fat_readdir_dirent_gen(
|
static void _fygue_fat_readdir_dirent_gen(
|
||||||
struct _fat_info *finfo,
|
struct _fat_info *finfo,
|
||||||
struct _fat_dirent *dirent
|
struct _fat_dirent *dirent
|
||||||
) {
|
) {
|
||||||
struct fygue_fat_dirent *current;
|
struct fygue_fat_dirent *current;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
current = finfo->current;
|
current = finfo->current;
|
||||||
while (finfo->idx > 0)
|
while (finfo->idx > 0)
|
||||||
current->name[idx++] = finfo->filename[--finfo->idx];
|
current->name[idx++] = finfo->filename[--finfo->idx];
|
||||||
current->name[idx] = 0x00;
|
current->name[idx] = 0x00;
|
||||||
current->attribute = dirent->DIR_Attr;
|
current->attribute = dirent->DIR_Attr;
|
||||||
current->size = FAT_DWORD(dirent->DIR_FileSize);
|
current->size = FAT_DWORD(dirent->DIR_FileSize);
|
||||||
current->meta_addr = (uintptr_t)dirent;
|
current->meta_addr = (uintptr_t)dirent;
|
||||||
current->cluster_id = (
|
current->cluster_id = (
|
||||||
(FAT_WORD(dirent->DIR_FstClusHI) << 16) |
|
(FAT_WORD(dirent->DIR_FstClusHI) << 16) |
|
||||||
(FAT_WORD(dirent->DIR_FstClusLO) << 0)
|
(FAT_WORD(dirent->DIR_FstClusLO) << 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_fat_readdir_name_shard_update() - update internal name info */
|
/* _fygue_fat_readdir_name_shard_update() - update internal name info */
|
||||||
static int _fygue_fat_readdir_name_shard_update(
|
static int _fygue_fat_readdir_name_shard_update(
|
||||||
struct _fat_info *finfo,
|
struct _fat_info *finfo,
|
||||||
uint16_t buffer[13]
|
uint16_t buffer[13]
|
||||||
) {
|
) {
|
||||||
uint8_t b0;
|
uint8_t b0;
|
||||||
uint8_t b1;
|
uint8_t b1;
|
||||||
|
|
||||||
for (int i = 0 ; i < 13 ; i++)
|
for (int i = 0 ; i < 13 ; i++)
|
||||||
{
|
{
|
||||||
if (buffer[i] == 0x0000 || buffer[i] == 0xffff)
|
if (buffer[i] == 0x0000 || buffer[i] == 0xffff)
|
||||||
continue;
|
continue;
|
||||||
if (buffer[i] >= 0x20 && buffer[i] <= 0x7a) {
|
if (buffer[i] >= 0x20 && buffer[i] <= 0x7a) {
|
||||||
finfo->filename[finfo->idx++] = buffer[i] & 0x00ff;
|
finfo->filename[finfo->idx++] = buffer[i] & 0x00ff;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
b0 = (buffer[i] & 0x00ff) >> 0;
|
b0 = (buffer[i] & 0x00ff) >> 0;
|
||||||
b1 = (buffer[i] & 0xff00) >> 8;
|
b1 = (buffer[i] & 0xff00) >> 8;
|
||||||
if (
|
if (
|
||||||
(b0 >= 0x81 && b0 <= 0x9f) ||
|
(b0 >= 0x81 && b0 <= 0x9f) ||
|
||||||
(b0 >= 0xa1 && b0 <= 0xfc)
|
(b0 >= 0xa1 && b0 <= 0xfc)
|
||||||
) {
|
) {
|
||||||
if (b1 >= 0x40 && b1 <= 0xfc && b1 != 0x7f)
|
if (b1 >= 0x40 && b1 <= 0xfc && b1 != 0x7f)
|
||||||
{
|
{
|
||||||
finfo->filename[finfo->idx++] = b1;
|
finfo->filename[finfo->idx++] = b1;
|
||||||
finfo->filename[finfo->idx++] = b0;
|
finfo->filename[finfo->idx++] = b0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_fat_readdir_name_prepare() - classic FAT handling */
|
/* _fygue_fat_readdir_name_prepare() - classic FAT handling */
|
||||||
static int _fygue_fat_readdir_name_fat_prepare(
|
static int _fygue_fat_readdir_name_fat_prepare(
|
||||||
struct _fat_info *finfo,
|
struct _fat_info *finfo,
|
||||||
struct _fat_dirent *dirent
|
struct _fat_dirent *dirent
|
||||||
) {
|
) {
|
||||||
uint16_t buffer[13];
|
uint16_t buffer[13];
|
||||||
bool need_dot;
|
bool need_dot;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
j = 13;
|
j = 13;
|
||||||
need_dot = false;
|
need_dot = false;
|
||||||
for (int i = 0 ; i < 11 ; i++)
|
for (int i = 0 ; i < 11 ; i++)
|
||||||
{
|
{
|
||||||
if (i == 8)
|
if (i == 8)
|
||||||
need_dot = true;
|
need_dot = true;
|
||||||
if (dirent->DIR_Name[i] == 0x20)
|
if (dirent->DIR_Name[i] == 0x20)
|
||||||
continue;
|
continue;
|
||||||
if (need_dot) {
|
if (need_dot) {
|
||||||
buffer[--j] = '.';
|
buffer[--j] = '.';
|
||||||
need_dot = false;
|
need_dot = false;
|
||||||
}
|
}
|
||||||
if (dirent->DIR_Name[i] >= 'A' && dirent->DIR_Name[i] <= 'Z') {
|
if (dirent->DIR_Name[i] >= 'A' && dirent->DIR_Name[i] <= 'Z') {
|
||||||
buffer[--j] = dirent->DIR_Name[i] + 0x20;
|
buffer[--j] = dirent->DIR_Name[i] + 0x20;
|
||||||
} else {
|
} else {
|
||||||
buffer[--j] = dirent->DIR_Name[i];
|
buffer[--j] = dirent->DIR_Name[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (--j >= 0)
|
while (--j >= 0)
|
||||||
buffer[j] = 0x0000;
|
buffer[j] = 0x0000;
|
||||||
finfo->idx = 0;
|
finfo->idx = 0;
|
||||||
return _fygue_fat_readdir_name_shard_update(finfo, buffer);
|
return _fygue_fat_readdir_name_shard_update(finfo, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_fat_readdir_name_update() - pre-generate filename info */
|
/* _fygue_fat_readdir_name_update() - pre-generate filename info */
|
||||||
static int _fygue_fat_readdir_name_vfat_prepare(
|
static int _fygue_fat_readdir_name_vfat_prepare(
|
||||||
struct _fat_info *finfo,
|
struct _fat_info *finfo,
|
||||||
struct _fat_dirname *dirname
|
struct _fat_dirname *dirname
|
||||||
) {
|
) {
|
||||||
uint16_t buffer[13];
|
uint16_t buffer[13];
|
||||||
|
|
||||||
buffer[0] = FAT_WORD(dirname->DIR_Char12);
|
buffer[0] = FAT_WORD(dirname->DIR_Char12);
|
||||||
buffer[1] = FAT_WORD(dirname->DIR_Char11);
|
buffer[1] = FAT_WORD(dirname->DIR_Char11);
|
||||||
buffer[2] = FAT_WORD(dirname->DIR_Char10);
|
buffer[2] = FAT_WORD(dirname->DIR_Char10);
|
||||||
buffer[3] = FAT_WORD(dirname->DIR_Char9);
|
buffer[3] = FAT_WORD(dirname->DIR_Char9);
|
||||||
buffer[4] = FAT_WORD(dirname->DIR_Char8);
|
buffer[4] = FAT_WORD(dirname->DIR_Char8);
|
||||||
buffer[5] = FAT_WORD(dirname->DIR_Char7);
|
buffer[5] = FAT_WORD(dirname->DIR_Char7);
|
||||||
buffer[6] = FAT_WORD(dirname->DIR_Char6);
|
buffer[6] = FAT_WORD(dirname->DIR_Char6);
|
||||||
buffer[7] = FAT_WORD(dirname->DIR_Char5);
|
buffer[7] = FAT_WORD(dirname->DIR_Char5);
|
||||||
buffer[8] = FAT_WORD(dirname->DIR_Char4);
|
buffer[8] = FAT_WORD(dirname->DIR_Char4);
|
||||||
buffer[9] = FAT_WORD(dirname->DIR_Char3);
|
buffer[9] = FAT_WORD(dirname->DIR_Char3);
|
||||||
buffer[10] = FAT_WORD(dirname->DIR_Char2);
|
buffer[10] = FAT_WORD(dirname->DIR_Char2);
|
||||||
buffer[11] = FAT_WORD(dirname->DIR_Char1);
|
buffer[11] = FAT_WORD(dirname->DIR_Char1);
|
||||||
buffer[12] = FAT_WORD(dirname->DIR_Char0);
|
buffer[12] = FAT_WORD(dirname->DIR_Char0);
|
||||||
return _fygue_fat_readdir_name_shard_update(finfo, buffer);
|
return _fygue_fat_readdir_name_shard_update(finfo, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -264,52 +264,52 @@ static int _fygue_fat_readdir_name_vfat_prepare(
|
||||||
* - properly handle broken chain (0x00, 0xe5, ...)
|
* - properly handle broken chain (0x00, 0xe5, ...)
|
||||||
* - properly handle `cursor_update()` error
|
* - properly handle `cursor_update()` error
|
||||||
* returns
|
* returns
|
||||||
* -3 internal error
|
* -3 internal error
|
||||||
* -2 invalid VFAT
|
* -2 invalid VFAT
|
||||||
* -1 invlaid VFAT (start)
|
* -1 invlaid VFAT (start)
|
||||||
* 0 success */
|
* 0 success */
|
||||||
static int _fygue_readdir_vfat(struct _fat_info *finfo)
|
static int _fygue_readdir_vfat(struct _fat_info *finfo)
|
||||||
{
|
{
|
||||||
struct _fat_dirname *dirname;
|
struct _fat_dirname *dirname;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
dirname = (void*)finfo->dir->dirent_current_addr;
|
dirname = (void*)finfo->dir->dirent_current_addr;
|
||||||
if (dirname->DIR_Sequence.last == 0) {
|
if (dirname->DIR_Sequence.last == 0) {
|
||||||
finfo->dir->dirty = true;
|
finfo->dir->dirty = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
finfo->idx = 0;
|
finfo->idx = 0;
|
||||||
count = dirname->DIR_Sequence.id;
|
count = dirname->DIR_Sequence.id;
|
||||||
do {
|
do {
|
||||||
dirname = (void*)finfo->dir->dirent_current_addr;
|
dirname = (void*)finfo->dir->dirent_current_addr;
|
||||||
if (dirname->DIR_Attr != 0x0f)
|
if (dirname->DIR_Attr != 0x0f)
|
||||||
return -2;
|
return -2;
|
||||||
if (dirname->DIR_Sequence.id != count)
|
if (dirname->DIR_Sequence.id != count)
|
||||||
return -2;
|
return -2;
|
||||||
if (_fygue_fat_readdir_name_vfat_prepare(finfo, dirname) != 0)
|
if (_fygue_fat_readdir_name_vfat_prepare(finfo, dirname) != 0)
|
||||||
return -2;
|
return -2;
|
||||||
if (_fygue_fat_readdir_cursor_update(finfo) != 0)
|
if (_fygue_fat_readdir_cursor_update(finfo) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
count -= 1;
|
count -= 1;
|
||||||
} while (count >= 1);
|
} while (count >= 1);
|
||||||
_fygue_fat_readdir_dirent_gen(
|
_fygue_fat_readdir_dirent_gen(
|
||||||
finfo,
|
finfo,
|
||||||
(void*)finfo->dir->dirent_current_addr
|
(void*)finfo->dir->dirent_current_addr
|
||||||
);
|
);
|
||||||
finfo->dir->dirty = true;
|
finfo->dir->dirty = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_readdir_fat() - handle FAT dirent generation */
|
/* _fygue_readdir_fat() - handle FAT dirent generation */
|
||||||
static int _fygue_readdir_fat(struct _fat_info *finfo)
|
static int _fygue_readdir_fat(struct _fat_info *finfo)
|
||||||
{
|
{
|
||||||
struct _fat_dirent *dirent;
|
struct _fat_dirent *dirent;
|
||||||
|
|
||||||
dirent = (void*)finfo->dir->dirent_current_addr;
|
dirent = (void*)finfo->dir->dirent_current_addr;
|
||||||
_fygue_fat_readdir_name_fat_prepare(finfo, dirent);
|
_fygue_fat_readdir_name_fat_prepare(finfo, dirent);
|
||||||
_fygue_fat_readdir_dirent_gen(finfo, dirent);
|
_fygue_fat_readdir_dirent_gen(finfo, dirent);
|
||||||
finfo->dir->dirty = true;
|
finfo->dir->dirty = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_readdir_fat_check() - check FAT type
|
/* _fygue_readdir_fat_check() - check FAT type
|
||||||
|
@ -317,54 +317,54 @@ static int _fygue_readdir_fat(struct _fat_info *finfo)
|
||||||
* notes
|
* notes
|
||||||
* check special first character of the FAT entry and try to determine
|
* check special first character of the FAT entry and try to determine
|
||||||
* if it is:
|
* if it is:
|
||||||
* 0x00 unused entry and all remaning entry will be unused
|
* 0x00 unused entry and all remaning entry will be unused
|
||||||
* 0xe5 unused entry
|
* 0xe5 unused entry
|
||||||
* 0x2e special "." or ".." entry
|
* 0x2e special "." or ".." entry
|
||||||
* then check the dirent attribute to distinguish an VFAT entry from an
|
* then check the dirent attribute to distinguish an VFAT entry from an
|
||||||
* classic FAT entry
|
* classic FAT entry
|
||||||
*
|
*
|
||||||
* return
|
* return
|
||||||
* -4 unsupported enty (volume ID)
|
* -4 unsupported enty (volume ID)
|
||||||
* -3 this is a end-of-dirent entry (0x00)
|
* -3 this is a end-of-dirent entry (0x00)
|
||||||
* -2 this is an unused entry (0xe5)
|
* -2 this is an unused entry (0xe5)
|
||||||
* -1 this is a special "." or ".." entry
|
* -1 this is a special "." or ".." entry
|
||||||
* 0 this is a classic FAT entry
|
* 0 this is a classic FAT entry
|
||||||
* 1 this is a VFAT entry */
|
* 1 this is a VFAT entry */
|
||||||
static int _fygue_readdir_fat_check(struct _fat_info *finfo)
|
static int _fygue_readdir_fat_check(struct _fat_info *finfo)
|
||||||
{
|
{
|
||||||
struct _fat_dirent *dirent;
|
struct _fat_dirent *dirent;
|
||||||
|
|
||||||
dirent = (void*)finfo->dir->dirent_current_addr;
|
dirent = (void*)finfo->dir->dirent_current_addr;
|
||||||
switch (dirent->DIR_Name[0])
|
switch (dirent->DIR_Name[0])
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
finfo->dir->end_of_dirent = true;
|
finfo->dir->end_of_dirent = true;
|
||||||
return -3;
|
return -3;
|
||||||
case 0xe5:
|
case 0xe5:
|
||||||
finfo->dir->dirty = true;
|
finfo->dir->dirty = true;
|
||||||
return -2;
|
return -2;
|
||||||
case 0x2e:
|
case 0x2e:
|
||||||
if (dirent->DIR_Name[1] == '.') {
|
if (dirent->DIR_Name[1] == '.') {
|
||||||
finfo->filename[0] = '.';
|
finfo->filename[0] = '.';
|
||||||
finfo->filename[1] = '.';
|
finfo->filename[1] = '.';
|
||||||
finfo->filename[2] = '\0';
|
finfo->filename[2] = '\0';
|
||||||
finfo->idx = 2;
|
finfo->idx = 2;
|
||||||
} else {
|
} else {
|
||||||
finfo->filename[0] = '.';
|
finfo->filename[0] = '.';
|
||||||
finfo->filename[1] = '\0';
|
finfo->filename[1] = '\0';
|
||||||
finfo->idx = 1;
|
finfo->idx = 1;
|
||||||
}
|
}
|
||||||
_fygue_fat_readdir_dirent_gen(finfo, dirent);
|
_fygue_fat_readdir_dirent_gen(finfo, dirent);
|
||||||
finfo->dir->dirty = true;
|
finfo->dir->dirty = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (dirent->DIR_Attr == 0x0f)
|
if (dirent->DIR_Attr == 0x0f)
|
||||||
return 1;
|
return 1;
|
||||||
if ((dirent->DIR_Attr & 0x08) != 0) {
|
if ((dirent->DIR_Attr & 0x08) != 0) {
|
||||||
finfo->dir->dirty = true;
|
finfo->dir->dirty = true;
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -374,46 +374,46 @@ static int _fygue_readdir_fat_check(struct _fat_info *finfo)
|
||||||
/* fygue_fat_dir_read() - readdir-like primitive
|
/* fygue_fat_dir_read() - readdir-like primitive
|
||||||
*
|
*
|
||||||
* return
|
* return
|
||||||
* -2 internal error
|
* -2 internal error
|
||||||
* -1 argument error
|
* -1 argument error
|
||||||
* 0 success
|
* 0 success
|
||||||
* 1 no directory found */
|
* 1 no directory found */
|
||||||
int fygue_fat_dir_read(
|
int fygue_fat_dir_read(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct fygue_fat_dirent *current
|
struct fygue_fat_dirent *current
|
||||||
) {
|
) {
|
||||||
struct _fat_info finfo;
|
struct _fat_info finfo;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fat == NULL || current == NULL || dir == NULL)
|
if (fat == NULL || current == NULL || dir == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
finfo.fat = fat;
|
finfo.fat = fat;
|
||||||
finfo.current = current;
|
finfo.current = current;
|
||||||
finfo.dir = dir;
|
finfo.dir = dir;
|
||||||
finfo.filename = alloca(256 * sizeof(uint8_t));
|
finfo.filename = alloca(256 * sizeof(uint8_t));
|
||||||
if (finfo.filename == NULL)
|
if (finfo.filename == NULL)
|
||||||
return -2;
|
return -2;
|
||||||
while (dir->end_of_dirent == false)
|
while (dir->end_of_dirent == false)
|
||||||
{
|
{
|
||||||
if (finfo.dir->dirty)
|
if (finfo.dir->dirty)
|
||||||
{
|
{
|
||||||
if (_fygue_fat_readdir_cursor_update(&finfo) != 0)
|
if (_fygue_fat_readdir_cursor_update(&finfo) != 0)
|
||||||
break;
|
break;
|
||||||
finfo.dir->dirty = false;
|
finfo.dir->dirty = false;
|
||||||
}
|
}
|
||||||
rc = _fygue_readdir_fat_check(&finfo);
|
rc = _fygue_readdir_fat_check(&finfo);
|
||||||
if (rc == -3)
|
if (rc == -3)
|
||||||
break;
|
break;
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
return 0;
|
return 0;
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
continue;
|
continue;
|
||||||
if (rc == 0 && _fygue_readdir_fat(&finfo) == 0)
|
if (rc == 0 && _fygue_readdir_fat(&finfo) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (rc == 1 && _fygue_readdir_vfat(&finfo) == 0)
|
if (rc == 1 && _fygue_readdir_vfat(&finfo) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dir->end_of_dirent = true;
|
dir->end_of_dirent = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,31 +8,31 @@
|
||||||
/* _get_mode(): get "pseudo" file mode */
|
/* _get_mode(): get "pseudo" file mode */
|
||||||
static mode_t _get_mode(struct fygue_fat_dir *dir)
|
static mode_t _get_mode(struct fygue_fat_dir *dir)
|
||||||
{
|
{
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
|
||||||
mode = 0777;
|
mode = 0777;
|
||||||
if (dir->attribute & FYGUE_FAT_ATTR_READ_ONLY)
|
if (dir->attribute & FYGUE_FAT_ATTR_READ_ONLY)
|
||||||
mode = 0444;
|
mode = 0444;
|
||||||
if (dir->attribute & FYGUE_FAT_ATTR_DIRECTORY)
|
if (dir->attribute & FYGUE_FAT_ATTR_DIRECTORY)
|
||||||
return mode | S_IFDIR;
|
return mode | S_IFDIR;
|
||||||
return S_IFREG | 0777;
|
return S_IFREG | 0777;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _get_block_size(): return one cluster size */
|
/* _get_block_size(): return one cluster size */
|
||||||
static int _get_block_size(struct fygue_fat *fat)
|
static int _get_block_size(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
return (fat->SectorSize * fat->SectorPerClus);
|
return (fat->SectorSize * fat->SectorPerClus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _get_block_nb(): count the number of cluster */
|
/* _get_block_nb(): count the number of cluster */
|
||||||
static int _get_block_nb(struct fygue_fat *fat, int cluster)
|
static int _get_block_nb(struct fygue_fat *fat, int cluster)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
while (fygue_fat_cluster_get_next(fat, &cluster) == 0)
|
while (fygue_fat_cluster_get_next(fat, &cluster) == 0)
|
||||||
count += 1;
|
count += 1;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -41,26 +41,26 @@ static int _get_block_nb(struct fygue_fat *fat, int cluster)
|
||||||
|
|
||||||
/* fygue_fat_dir_stat(): directory-specific stat primitive */
|
/* fygue_fat_dir_stat(): directory-specific stat primitive */
|
||||||
int fygue_fat_dir_stat(
|
int fygue_fat_dir_stat(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct stat *statbuf
|
struct stat *statbuf
|
||||||
) {
|
) {
|
||||||
if (fat == NULL || dir == NULL || statbuf == NULL) {
|
if (fat == NULL || dir == NULL || statbuf == NULL) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
statbuf->st_dev = 0; /* not supported */
|
statbuf->st_dev = 0; /* not supported */
|
||||||
statbuf->st_ino = dir->cluster_entry;
|
statbuf->st_ino = dir->cluster_entry;
|
||||||
statbuf->st_mode = _get_mode(dir);
|
statbuf->st_mode = _get_mode(dir);
|
||||||
statbuf->st_nlink = 0; /* not supported */
|
statbuf->st_nlink = 0; /* not supported */
|
||||||
statbuf->st_uid = 0; /* not supported */
|
statbuf->st_uid = 0; /* not supported */
|
||||||
statbuf->st_gid = 0; /* not supported */
|
statbuf->st_gid = 0; /* not supported */
|
||||||
statbuf->st_rdev = 0; /* not supported */
|
statbuf->st_rdev = 0; /* not supported */
|
||||||
statbuf->st_size = 0;
|
statbuf->st_size = 0;
|
||||||
statbuf->st_atime = 0; /* not supported */
|
statbuf->st_atime = 0; /* not supported */
|
||||||
statbuf->st_mtime = 0; /* not supported */
|
statbuf->st_mtime = 0; /* not supported */
|
||||||
statbuf->st_ctime = 0; /* not supported */
|
statbuf->st_ctime = 0; /* not supported */
|
||||||
statbuf->st_blksize = _get_block_size(fat);
|
statbuf->st_blksize = _get_block_size(fat);
|
||||||
statbuf->st_blocks = _get_block_nb(fat, dir->cluster_entry);
|
statbuf->st_blocks = _get_block_nb(fat, dir->cluster_entry);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,33 +2,33 @@
|
||||||
|
|
||||||
/* 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 cluster_id
|
||||||
) {
|
) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fat == NULL || dir == NULL)
|
if (fat == NULL || dir == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
dir->dirty = false;
|
dir->dirty = false;
|
||||||
dir->sector_count = 0;
|
dir->sector_count = 0;
|
||||||
dir->dirent_cursor = 0;
|
dir->dirent_cursor = 0;
|
||||||
dir->end_of_dirent = false;
|
dir->end_of_dirent = false;
|
||||||
dir->cluster_entry = cluster_id;
|
dir->cluster_entry = cluster_id;
|
||||||
dir->cluster_current = dir->cluster_entry;
|
dir->cluster_current = dir->cluster_entry;
|
||||||
rc = fygue_fat_cluster_get_sector(
|
rc = fygue_fat_cluster_get_sector(
|
||||||
fat,
|
fat,
|
||||||
dir->cluster_current,
|
dir->cluster_current,
|
||||||
&dir->sector_id
|
&dir->sector_id
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -2;
|
return -2;
|
||||||
rc = fygue_fat_sector_get_addr(
|
rc = fygue_fat_sector_get_addr(
|
||||||
fat,
|
fat,
|
||||||
&dir->dirent_current_addr,
|
&dir->dirent_current_addr,
|
||||||
dir->sector_id
|
dir->sector_id
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -3;
|
return -3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
/* fygue_fat_file_close(): close primitive */
|
/* fygue_fat_file_close(): close primitive */
|
||||||
int fygue_fat_file_close(struct fygue_fat *fat, struct fygue_fat_file *file)
|
int fygue_fat_file_close(struct fygue_fat *fat, struct fygue_fat_file *file)
|
||||||
{
|
{
|
||||||
if (fat == NULL || file == NULL)
|
if (fat == NULL || file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (file->chunk != NULL)
|
if (file->chunk != NULL)
|
||||||
free(file->chunk);
|
free(file->chunk);
|
||||||
memset(file, 0x00, sizeof(struct fygue_fat_file));
|
memset(file, 0x00, sizeof(struct fygue_fat_file));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,22 @@
|
||||||
|
|
||||||
/* fygue_fat_file_open(): generate file information */
|
/* fygue_fat_file_open(): generate file information */
|
||||||
int fygue_fat_file_open(
|
int fygue_fat_file_open(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
struct fygue_fat_dirent *dirent
|
struct fygue_fat_dirent *dirent
|
||||||
) {
|
) {
|
||||||
memset(file, 0x00, sizeof(struct fygue_fat_file));
|
memset(file, 0x00, sizeof(struct fygue_fat_file));
|
||||||
file->attribute = dirent->attribute;
|
file->attribute = dirent->attribute;
|
||||||
file->cluster_entry = dirent->cluster_id;
|
file->cluster_entry = dirent->cluster_id;
|
||||||
file->size = dirent->size;
|
file->size = dirent->size;
|
||||||
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, dirent->cluster_id) != 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;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,51 +2,44 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
|
|
||||||
uintptr_t debug_read_addr = 0;
|
|
||||||
size_t debug_read_size = 0;
|
|
||||||
int debug_read_off = 0;
|
|
||||||
|
|
||||||
/* fygue_fat_file_read(): read primitive */
|
/* fygue_fat_file_read(): read primitive */
|
||||||
int fygue_fat_file_read(
|
int fygue_fat_file_read(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
uintptr_t chunk_data_addr;
|
uintptr_t chunk_data_addr;
|
||||||
size_t chunk_data_available;
|
size_t chunk_data_available;
|
||||||
size_t chunk_data_offset;
|
size_t chunk_data_offset;
|
||||||
size_t read;
|
size_t read;
|
||||||
|
|
||||||
if (fat == NULL || file == NULL || buffer == NULL)
|
if (fat == NULL || file == NULL || buffer == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (file->chunk == NULL)
|
if (file->chunk == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
read = 0;
|
read = 0;
|
||||||
chunk_data_offset = file->chunk_rd_offset;
|
chunk_data_offset = file->chunk_rd_offset;
|
||||||
while (read < size)
|
while (read < size)
|
||||||
{
|
{
|
||||||
if (file->chunk_rd_index >= file->chunk_count)
|
if (file->chunk_rd_index >= file->chunk_count)
|
||||||
break;
|
break;
|
||||||
chunk_data_addr = file->chunk[file->chunk_rd_index].addr;
|
chunk_data_addr = file->chunk[file->chunk_rd_index].addr;
|
||||||
chunk_data_addr += chunk_data_offset;
|
chunk_data_addr += chunk_data_offset;
|
||||||
chunk_data_available = file->chunk[file->chunk_rd_index].size;
|
chunk_data_available = file->chunk[file->chunk_rd_index].size;
|
||||||
chunk_data_available -= chunk_data_offset;
|
chunk_data_available -= chunk_data_offset;
|
||||||
if (read + chunk_data_available > size)
|
if (read + chunk_data_available > size)
|
||||||
{
|
{
|
||||||
debug_read_addr = chunk_data_addr;
|
chunk_data_offset += size - read;
|
||||||
debug_read_size = size - read;
|
memcpy(buffer, (void*)chunk_data_addr, size - read);
|
||||||
debug_read_off = chunk_data_offset;
|
read += size - read;
|
||||||
chunk_data_offset += size - read;
|
break;
|
||||||
memcpy(buffer, (void*)chunk_data_addr, size - read);
|
}
|
||||||
read += size - read;
|
memcpy(buffer, (void*)chunk_data_addr, chunk_data_available);
|
||||||
break;
|
read += chunk_data_available;
|
||||||
}
|
file->chunk_rd_index += 1;
|
||||||
memcpy(buffer, (void*)chunk_data_addr, chunk_data_available);
|
chunk_data_offset = 0;
|
||||||
read += chunk_data_available;
|
}
|
||||||
file->chunk_rd_index += 1;
|
file->chunk_rd_offset = chunk_data_offset;
|
||||||
chunk_data_offset = 0;
|
return read;
|
||||||
}
|
|
||||||
file->chunk_rd_offset = chunk_data_offset;
|
|
||||||
return read;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,29 @@
|
||||||
|
|
||||||
/* fygue_fat_file_seek(): seek primitive */
|
/* fygue_fat_file_seek(): seek primitive */
|
||||||
int fygue_fat_file_seek(
|
int fygue_fat_file_seek(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
off_t offset
|
off_t offset
|
||||||
) {
|
) {
|
||||||
off_t offset_current;
|
off_t offset_current;
|
||||||
|
|
||||||
if (fat == NULL || file == NULL)
|
if (fat == NULL || file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
offset_current = 0;
|
offset_current = 0;
|
||||||
file->chunk_rd_index = 0;
|
file->chunk_rd_index = 0;
|
||||||
file->chunk_rd_offset = 0;
|
file->chunk_rd_offset = 0;
|
||||||
for (int i = 0; i < file->chunk_count; i++)
|
for (int i = 0; i < file->chunk_count; i++)
|
||||||
{
|
{
|
||||||
offset_current += file->chunk[i].size;
|
offset_current += file->chunk[i].size;
|
||||||
if (offset_current > offset) {
|
if (offset_current > offset) {
|
||||||
file->chunk_rd_offset = (
|
file->chunk_rd_offset = (
|
||||||
file->chunk[i].size - (offset_current - offset)
|
file->chunk[i].size - (offset_current - offset)
|
||||||
);
|
);
|
||||||
file->cursor = offset;
|
file->cursor = offset;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
file->chunk_rd_index += 1;
|
file->chunk_rd_index += 1;
|
||||||
}
|
}
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,26 +8,26 @@
|
||||||
/* _get_mode(): get "pseudo" file mode */
|
/* _get_mode(): get "pseudo" file mode */
|
||||||
static mode_t _get_mode(int attribute)
|
static mode_t _get_mode(int attribute)
|
||||||
{
|
{
|
||||||
if (attribute & FYGUE_FAT_ATTR_READ_ONLY)
|
if (attribute & FYGUE_FAT_ATTR_READ_ONLY)
|
||||||
return S_IFREG | 0444;
|
return S_IFREG | 0444;
|
||||||
return S_IFREG | 0777;
|
return S_IFREG | 0777;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _get_block_size(): return one cluster size */
|
/* _get_block_size(): return one cluster size */
|
||||||
static int _get_block_size(struct fygue_fat *fat)
|
static int _get_block_size(struct fygue_fat *fat)
|
||||||
{
|
{
|
||||||
return (fat->SectorSize * fat->SectorPerClus);
|
return (fat->SectorSize * fat->SectorPerClus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _get_block_nb(): count the number of cluster */
|
/* _get_block_nb(): count the number of cluster */
|
||||||
static int _get_block_nb(struct fygue_fat *fat, int cluster)
|
static int _get_block_nb(struct fygue_fat *fat, int cluster)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
count = 1;
|
count = 1;
|
||||||
while (fygue_fat_cluster_get_next(fat, &cluster) == 0)
|
while (fygue_fat_cluster_get_next(fat, &cluster) == 0)
|
||||||
count += 1;
|
count += 1;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -36,26 +36,26 @@ static int _get_block_nb(struct fygue_fat *fat, int cluster)
|
||||||
|
|
||||||
/* fygue_fat_file_stat(): directory-specific stat primitive */
|
/* fygue_fat_file_stat(): directory-specific stat primitive */
|
||||||
int fygue_fat_file_stat(
|
int fygue_fat_file_stat(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
struct stat *statbuf
|
struct stat *statbuf
|
||||||
) {
|
) {
|
||||||
if (fat == NULL || file == NULL || statbuf == NULL) {
|
if (fat == NULL || file == NULL || statbuf == NULL) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
statbuf->st_dev = 0; /* not supported */
|
statbuf->st_dev = 0; /* not supported */
|
||||||
statbuf->st_ino = file->cluster_entry;
|
statbuf->st_ino = file->cluster_entry;
|
||||||
statbuf->st_mode = _get_mode(file->attribute);
|
statbuf->st_mode = _get_mode(file->attribute);
|
||||||
statbuf->st_nlink = 0; /* not supported */
|
statbuf->st_nlink = 0; /* not supported */
|
||||||
statbuf->st_uid = 0; /* not supported */
|
statbuf->st_uid = 0; /* not supported */
|
||||||
statbuf->st_gid = 0; /* not supported */
|
statbuf->st_gid = 0; /* not supported */
|
||||||
statbuf->st_rdev = 0; /* not supported */
|
statbuf->st_rdev = 0; /* not supported */
|
||||||
statbuf->st_size = file->size;
|
statbuf->st_size = file->size;
|
||||||
statbuf->st_atime = 0; /* not supported */
|
statbuf->st_atime = 0; /* not supported */
|
||||||
statbuf->st_mtime = 0; /* not supported */
|
statbuf->st_mtime = 0; /* not supported */
|
||||||
statbuf->st_ctime = 0; /* not supported */
|
statbuf->st_ctime = 0; /* not supported */
|
||||||
statbuf->st_blksize = _get_block_size(fat);
|
statbuf->st_blksize = _get_block_size(fat);
|
||||||
statbuf->st_blocks = _get_block_nb(fat, file->cluster_entry);
|
statbuf->st_blocks = _get_block_nb(fat, file->cluster_entry);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,50 +7,50 @@
|
||||||
|
|
||||||
/* _fygue_chunk_table_update(): update chunk table */
|
/* _fygue_chunk_table_update(): update chunk table */
|
||||||
static int _fygue_chunk_table_update(
|
static int _fygue_chunk_table_update(
|
||||||
struct fygue_fat_file *file,
|
struct fygue_fat_file *file,
|
||||||
uintptr_t cluster_addr
|
uintptr_t cluster_addr
|
||||||
) {
|
) {
|
||||||
uintptr_t cluster_addr_prev;
|
uintptr_t cluster_addr_prev;
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
||||||
if (file->chunk_count > 0)
|
if (file->chunk_count > 0)
|
||||||
{
|
{
|
||||||
cluster_addr_prev = file->chunk[file->chunk_count - 1].addr;
|
cluster_addr_prev = file->chunk[file->chunk_count - 1].addr;
|
||||||
cluster_addr_prev += file->chunk[file->chunk_count - 1].size;
|
cluster_addr_prev += file->chunk[file->chunk_count - 1].size;
|
||||||
if (cluster_addr == cluster_addr_prev)
|
if (cluster_addr == cluster_addr_prev)
|
||||||
{
|
{
|
||||||
file->chunk[file->chunk_count - 1].size += 8*512;
|
file->chunk[file->chunk_count - 1].size += 8*512;
|
||||||
file->chunk[file->chunk_count - 1].cluster_count += 1;
|
file->chunk[file->chunk_count - 1].cluster_count += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (file->chunk_count >= file->chunk_table_max_index)
|
if (file->chunk_count >= file->chunk_table_max_index)
|
||||||
{
|
{
|
||||||
tmp = reallocarray(
|
tmp = reallocarray(
|
||||||
file->chunk,
|
file->chunk,
|
||||||
file->chunk_table_max_index + 1,
|
file->chunk_table_max_index + 1,
|
||||||
sizeof(*file->chunk)
|
sizeof(*file->chunk)
|
||||||
);
|
);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
file->chunk = tmp;
|
file->chunk = tmp;
|
||||||
file->chunk_table_max_index += 1;
|
file->chunk_table_max_index += 1;
|
||||||
}
|
}
|
||||||
file->chunk[file->chunk_count].size = 8*512;
|
file->chunk[file->chunk_count].size = 8*512;
|
||||||
file->chunk[file->chunk_count].addr = cluster_addr;
|
file->chunk[file->chunk_count].addr = cluster_addr;
|
||||||
file->chunk[file->chunk_count].cluster_count = 1;
|
file->chunk[file->chunk_count].cluster_count = 1;
|
||||||
file->chunk_count += 1;
|
file->chunk_count += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_chunk_error(): invalidate the chunk table */
|
/* _fygue_chunk_error(): invalidate the chunk table */
|
||||||
static int _fygue_chunk_error(struct fygue_fat_file *file)
|
static int _fygue_chunk_error(struct fygue_fat_file *file)
|
||||||
{
|
{
|
||||||
if (file->chunk == NULL)
|
if (file->chunk == NULL)
|
||||||
free(file->chunk);
|
free(file->chunk);
|
||||||
file->chunk_table_max_index = 0;
|
file->chunk_table_max_index = 0;
|
||||||
file->chunk_count = 0;
|
file->chunk_count = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -59,26 +59,26 @@ 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
|
int cluster_id
|
||||||
) {
|
) {
|
||||||
uintptr_t cluster_addr;
|
uintptr_t cluster_addr;
|
||||||
|
|
||||||
if (fat == NULL || file == NULL)
|
if (fat == NULL || file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
file->chunk_count = 0;
|
file->chunk_count = 0;
|
||||||
file->cluster_entry = cluster_id;
|
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)
|
||||||
return _fygue_chunk_error(file);
|
return _fygue_chunk_error(file);
|
||||||
if (_fygue_chunk_table_update(file, cluster_addr) != 0)
|
if (_fygue_chunk_table_update(file, cluster_addr) != 0)
|
||||||
return _fygue_chunk_error(file);
|
return _fygue_chunk_error(file);
|
||||||
if (fygue_fat_cluster_get_next(fat, &cluster_id) != 0)
|
if (fygue_fat_cluster_get_next(fat, &cluster_id) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fygue_fat_file_seek(fat, file, file->cursor) != 0)
|
if (fygue_fat_file_seek(fat, file, file->cursor) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,55 +13,55 @@
|
||||||
* - assume that size is not NULL
|
* - assume that size is not NULL
|
||||||
* - assume that prefix can start with '/' */
|
* - assume that prefix can start with '/' */
|
||||||
static int _fygue_path_get_name(
|
static int _fygue_path_get_name(
|
||||||
char const **prefix,
|
char const **prefix,
|
||||||
char const **filename,
|
char const **filename,
|
||||||
size_t *len
|
size_t *len
|
||||||
) {
|
) {
|
||||||
while ((*prefix)[0] == '/') {
|
while ((*prefix)[0] == '/') {
|
||||||
*prefix = &((*prefix)[1]);
|
*prefix = &((*prefix)[1]);
|
||||||
}
|
}
|
||||||
if ((*prefix)[0] == '\0')
|
if ((*prefix)[0] == '\0')
|
||||||
return -1;
|
return -1;
|
||||||
*len = 0;
|
*len = 0;
|
||||||
*filename = *prefix;
|
*filename = *prefix;
|
||||||
while ((*prefix)[0] != '\0' && (*prefix)[0] != '/') {
|
while ((*prefix)[0] != '\0' && (*prefix)[0] != '/') {
|
||||||
*len += 1;
|
*len += 1;
|
||||||
*prefix = &((*prefix)[1]);
|
*prefix = &((*prefix)[1]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_opendir_find() - try to find the directory entry */
|
/* _fygue_opendir_find() - try to find the directory entry */
|
||||||
static int _fygue_dirent_find(
|
static int _fygue_dirent_find(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
struct fygue_fat_dir *dir,
|
struct fygue_fat_dir *dir,
|
||||||
struct fygue_fat_dirent *dirent,
|
struct fygue_fat_dirent *dirent,
|
||||||
char const *start,
|
char const *start,
|
||||||
size_t len
|
size_t len
|
||||||
) {
|
) {
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (fygue_fat_dir_read(fat, dir, dirent) != 0)
|
if (fygue_fat_dir_read(fat, dir, dirent) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (strncmp(dirent->name, start, len) != 0)
|
if (strncmp(dirent->name, start, len) != 0)
|
||||||
continue;
|
continue;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _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_descriptor *desc,
|
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)) {
|
||||||
desc->type = FYGUE_FAT_DESC_TYPE_DIR;
|
desc->type = FYGUE_FAT_DESC_TYPE_DIR;
|
||||||
return fygue_fat_dir_open(fat, &(desc->dir), dirent);
|
return fygue_fat_dir_open(fat, &(desc->dir), dirent);
|
||||||
} else {
|
} else {
|
||||||
desc->type = FYGUE_FAT_DESC_TYPE_FILE;
|
desc->type = FYGUE_FAT_DESC_TYPE_FILE;
|
||||||
return fygue_fat_file_open(fat, &(desc->file), dirent);
|
return fygue_fat_file_open(fat, &(desc->file), dirent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -73,39 +73,39 @@ static int _fygue_resolve_set(
|
||||||
* notes
|
* notes
|
||||||
* - assume that the path is clean */
|
* - assume that the path is clean */
|
||||||
int fygue_fat_open(
|
int fygue_fat_open(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_fat_descriptor *desc
|
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;
|
||||||
char const *prefix;
|
char const *prefix;
|
||||||
char const *start;
|
char const *start;
|
||||||
size_t len;
|
size_t len;
|
||||||
bool is_root;
|
bool is_root;
|
||||||
|
|
||||||
if (fat == NULL || path == NULL || desc == NULL)
|
if (fat == NULL || path == NULL || desc == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
prefix = path;
|
prefix = path;
|
||||||
is_root = true;
|
is_root = true;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (is_root) {
|
if (is_root) {
|
||||||
if (fygue_fat_dir_open(fat, &dir, NULL) != 0)
|
if (fygue_fat_dir_open(fat, &dir, NULL) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
if (_fygue_path_get_name(&prefix, &start, &len) != 0)
|
if (_fygue_path_get_name(&prefix, &start, &len) != 0)
|
||||||
break;
|
break;
|
||||||
is_root = false;
|
is_root = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (_fygue_dirent_find(fat, &dir, &dirent, start, len) != 0)
|
if (_fygue_dirent_find(fat, &dir, &dirent, start, len) != 0)
|
||||||
return -4;
|
return -4;
|
||||||
if (_fygue_path_get_name(&prefix, &start, &len) != 0)
|
if (_fygue_path_get_name(&prefix, &start, &len) != 0)
|
||||||
break;
|
break;
|
||||||
if (fygue_fat_dir_open(fat, &dir, &dirent) != 0)
|
if (fygue_fat_dir_open(fat, &dir, &dirent) != 0)
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
if (is_root)
|
if (is_root)
|
||||||
return _fygue_resolve_set(fat, desc, NULL);
|
return _fygue_resolve_set(fat, desc, NULL);
|
||||||
return _fygue_resolve_set(fat, desc, &dirent);
|
return _fygue_resolve_set(fat, desc, &dirent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
/* _bfile_cluster_metadata - special cluster metadata information */
|
/* _bfile_cluster_metadata - special cluster metadata information */
|
||||||
struct _bfile_cluster_metadata
|
struct _bfile_cluster_metadata
|
||||||
{
|
{
|
||||||
uint8_t bitmask[2];
|
uint8_t bitmask[2];
|
||||||
uint32_t fcluster_version;
|
uint32_t fcluster_version;
|
||||||
uint16_t lcluster_id;
|
uint16_t lcluster_id;
|
||||||
uint16_t fcluster_crc;
|
uint16_t fcluster_crc;
|
||||||
uint8_t constant[24];
|
uint8_t constant[24];
|
||||||
uint8_t signature[3];
|
uint8_t signature[3];
|
||||||
uint8_t ecc_bitmask_position[3];
|
uint8_t ecc_bitmask_position[3];
|
||||||
} GPACKED(1);
|
} GPACKED(1);
|
||||||
|
|
||||||
/* _fygue_flash_cluster_convert - ensure that the provided meta is valid
|
/* _fygue_flash_cluster_convert - ensure that the provided meta is valid
|
||||||
|
@ -31,9 +31,9 @@ struct _bfile_cluster_metadata
|
||||||
* - assume that fcluster is not NULL
|
* - assume that fcluster is not NULL
|
||||||
* - try using P1 information first then, P2 if this greedy-read fail
|
* - try using P1 information first then, P2 if this greedy-read fail
|
||||||
* - to ensure that the provided bfile metadata is valid we will perform
|
* - to ensure that the provided bfile metadata is valid we will perform
|
||||||
* some test (also performed by Casio). First, ensure that the
|
* some test (also performed by Casio). First, ensure that the
|
||||||
* fcluster "kind" is valid (only 0x88, 0x22 or 0x11 are known and
|
* fcluster "kind" is valid (only 0x88, 0x22 or 0x11 are known and
|
||||||
* used) and then ensure that the "constant" part is also valid
|
* used) and then ensure that the "constant" part is also valid
|
||||||
*
|
*
|
||||||
* todo : ensure checksum
|
* todo : ensure checksum
|
||||||
* todo : ensure ecc handling (?)
|
* todo : ensure ecc handling (?)
|
||||||
|
@ -42,73 +42,73 @@ struct _bfile_cluster_metadata
|
||||||
* return
|
* return
|
||||||
* -1 if the provided `fcluster` is not NULL
|
* -1 if the provided `fcluster` is not NULL
|
||||||
* -1 if the bfile metadata cannot be validated
|
* -1 if the bfile metadata cannot be validated
|
||||||
* 0 otherwise */
|
* 0 otherwise */
|
||||||
static int _fygue_flash_cluster_convert(
|
static int _fygue_flash_cluster_convert(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cluster *fcluster,
|
struct fygue_flash_cluster *fcluster,
|
||||||
uintptr_t meta
|
uintptr_t meta
|
||||||
) {
|
) {
|
||||||
#if 0
|
#if 0
|
||||||
static const uint8_t _constant1[] = {
|
static const uint8_t _constant1[] = {
|
||||||
0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff,
|
||||||
};
|
};
|
||||||
static const uint8_t _constant2[] = {
|
static const uint8_t _constant2[] = {
|
||||||
0x11, 0x11, 0x11, 0x22,
|
0x11, 0x11, 0x11, 0x22,
|
||||||
0x22, 0x22, 0x44, 0x44,
|
0x22, 0x22, 0x44, 0x44,
|
||||||
0x44, 0x88, 0x88, 0x88,
|
0x44, 0x88, 0x88, 0x88,
|
||||||
0x77, 0x77, 0x77, 0xbb,
|
0x77, 0x77, 0x77, 0xbb,
|
||||||
0xbb, 0xbb, 0xdd, 0xdd,
|
0xbb, 0xbb, 0xdd, 0xdd,
|
||||||
0xdd, 0xee, 0xee, 0xee,
|
0xdd, 0xee, 0xee, 0xee,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
struct _bfile_cluster_metadata *bfile_meta;
|
struct _bfile_cluster_metadata *bfile_meta;
|
||||||
|
|
||||||
if (flash == NULL || fcluster == NULL)
|
if (flash == NULL || fcluster == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
bfile_meta = (void*)(meta | 0xa0000000);
|
bfile_meta = (void*)(meta | 0xa0000000);
|
||||||
if (
|
if (
|
||||||
bfile_meta->signature[0] != 0x5a ||
|
bfile_meta->signature[0] != 0x5a ||
|
||||||
bfile_meta->signature[1] != 0x5a ||
|
bfile_meta->signature[1] != 0x5a ||
|
||||||
bfile_meta->signature[2] != 0x5a
|
bfile_meta->signature[2] != 0x5a
|
||||||
) {
|
) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
bfile_meta->bitmask[0] != 0x88 &&
|
bfile_meta->bitmask[0] != 0x88 &&
|
||||||
bfile_meta->bitmask[0] != 0x22 &&
|
bfile_meta->bitmask[0] != 0x22 &&
|
||||||
bfile_meta->bitmask[0] != 0x11
|
bfile_meta->bitmask[0] != 0x11
|
||||||
) {
|
) {
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
if (bfile_meta->bitmask[1] != 0x0f)
|
if (bfile_meta->bitmask[1] != 0x0f)
|
||||||
return -4;
|
return -4;
|
||||||
if (
|
if (
|
||||||
bfile_meta->bitmask[0] != 0x11 &&
|
bfile_meta->bitmask[0] != 0x11 &&
|
||||||
bfile_meta->lcluster_id != 0xffff
|
bfile_meta->lcluster_id != 0xffff
|
||||||
) {
|
) {
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
// on the fxcp400, have only some flash sector with the constants used
|
// on the fxcp400, have only some flash sector with the constants used
|
||||||
// in other device. Internally, on the fxcp400, Casio only perform
|
// in other device. Internally, on the fxcp400, Casio only perform
|
||||||
// a check an CRC that is performed on the whole cluster
|
// a check an CRC that is performed on the whole cluster
|
||||||
// TODO: CRC check
|
// TODO: CRC check
|
||||||
#if 0
|
#if 0
|
||||||
if (
|
if (
|
||||||
memcmp(&(bfile_meta->constant), _constant1, 0x18) != 0 &&
|
memcmp(&(bfile_meta->constant), _constant1, 0x18) != 0 &&
|
||||||
memcmp(&(bfile_meta->constant), _constant2, 0x18) != 0
|
memcmp(&(bfile_meta->constant), _constant2, 0x18) != 0
|
||||||
) {
|
) {
|
||||||
return -6;
|
return -6;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fcluster->lcluster_id = bfile_meta->lcluster_id;
|
fcluster->lcluster_id = bfile_meta->lcluster_id;
|
||||||
fcluster->kind = bfile_meta->bitmask[0];
|
fcluster->kind = bfile_meta->bitmask[0];
|
||||||
fcluster->version = bfile_meta->fcluster_version;
|
fcluster->version = bfile_meta->fcluster_version;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_flash_cluster_meta(): special metadata cluster handling
|
/* _fygue_flash_cluster_meta(): special metadata cluster handling
|
||||||
|
@ -118,25 +118,25 @@ static int _fygue_flash_cluster_convert(
|
||||||
* not have Bfile information. Generate a fake flash cluster with a
|
* not have Bfile information. Generate a fake flash cluster with a
|
||||||
* special custom kind to allow quick identification */
|
* special custom kind to allow quick identification */
|
||||||
static int _fygue_flash_cluster_meta(
|
static int _fygue_flash_cluster_meta(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cluster *fcluster,
|
struct fygue_flash_cluster *fcluster,
|
||||||
int fsector_id
|
int fsector_id
|
||||||
) {
|
) {
|
||||||
GAUTOTYPE geometry = &(flash->geometry);
|
GAUTOTYPE geometry = &(flash->geometry);
|
||||||
|
|
||||||
memset(fcluster, 0x00, sizeof(struct fygue_flash_cluster));
|
memset(fcluster, 0x00, sizeof(struct fygue_flash_cluster));
|
||||||
fcluster->kind = FYGUE_FCLUSTER_KIND_METADATA;
|
fcluster->kind = FYGUE_FCLUSTER_KIND_METADATA;
|
||||||
fcluster->lcluster_id = 0xffff;
|
fcluster->lcluster_id = 0xffff;
|
||||||
fcluster->fcluster_id = 0xffff;
|
fcluster->fcluster_id = 0xffff;
|
||||||
fcluster->fcluster_id_bfile = 0xffff;
|
fcluster->fcluster_id_bfile = 0xffff;
|
||||||
fcluster->version = 0xffffffff;
|
fcluster->version = 0xffffffff;
|
||||||
fcluster->meta_addr = 0xffffffff;
|
fcluster->meta_addr = 0xffffffff;
|
||||||
fcluster->data_addr = (
|
fcluster->data_addr = (
|
||||||
(geometry->phy_start | 0xa0000000) +
|
(geometry->phy_start | 0xa0000000) +
|
||||||
((fsector_id + 1) * geometry->fsector_size) -
|
((fsector_id + 1) * geometry->fsector_size) -
|
||||||
(8 * 512)
|
(8 * 512)
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_flash_cluster_details(): special flash sector details handling
|
/* _fygue_flash_cluster_details(): special flash sector details handling
|
||||||
|
@ -153,46 +153,46 @@ static int _fygue_flash_cluster_meta(
|
||||||
* one type.
|
* one type.
|
||||||
*
|
*
|
||||||
* for 64k cluster the 0xf3c0 offset can be calculated as:
|
* for 64k cluster the 0xf3c0 offset can be calculated as:
|
||||||
* 0x10000 - (8*512) = 0xf000 | sector size minus cluster size
|
* 0x10000 - (8*512) = 0xf000 | sector size minus cluster size
|
||||||
* 15 * 0x40 = 0x3c0 | skip all data cluster meta info */
|
* 15 * 0x40 = 0x3c0 | skip all data cluster meta info */
|
||||||
static int _fygue_flash_cluster_details(
|
static int _fygue_flash_cluster_details(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cluster *fcluster,
|
struct fygue_flash_cluster *fcluster,
|
||||||
int fsector_id
|
int fsector_id
|
||||||
) {
|
) {
|
||||||
GAUTOTYPE geometry = &(flash->geometry);
|
GAUTOTYPE geometry = &(flash->geometry);
|
||||||
volatile uint32_t *data32;
|
volatile uint32_t *data32;
|
||||||
uintptr_t meta;
|
uintptr_t meta;
|
||||||
uintptr_t data;
|
uintptr_t data;
|
||||||
|
|
||||||
memset(fcluster, 0x00, sizeof(struct fygue_flash_cluster));
|
memset(fcluster, 0x00, sizeof(struct fygue_flash_cluster));
|
||||||
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
|
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
|
||||||
data = (
|
data = (
|
||||||
(geometry->phy_start | 0xa0000000) +
|
(geometry->phy_start | 0xa0000000) +
|
||||||
(fsector_id * 0x10000) +
|
(fsector_id * 0x10000) +
|
||||||
(0xf3c0)
|
(0xf3c0)
|
||||||
);
|
);
|
||||||
meta = data + 512;
|
meta = data + 512;
|
||||||
} else {
|
} else {
|
||||||
data = (geometry->phy_start | 0xa0000000) + (fsector_id * 0x20000);
|
data = (geometry->phy_start | 0xa0000000) + (fsector_id * 0x20000);
|
||||||
meta = data + 0x1f000;
|
meta = data + 0x1f000;
|
||||||
}
|
}
|
||||||
if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0)
|
if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (fcluster->version != 0xffffffff)
|
if (fcluster->version != 0xffffffff)
|
||||||
return -2;
|
return -2;
|
||||||
data32 = (void*)data;
|
data32 = (void*)data;
|
||||||
if (
|
if (
|
||||||
((data32[0] ^ data32[1]) != 0xffffffff) ||
|
((data32[0] ^ data32[1]) != 0xffffffff) ||
|
||||||
((data32[2] ^ data32[3]) != 0xffffffff) ||
|
((data32[2] ^ data32[3]) != 0xffffffff) ||
|
||||||
((data32[4] ^ data32[5]) != 0xffffffff)
|
((data32[4] ^ data32[5]) != 0xffffffff)
|
||||||
) {
|
) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fcluster->data_addr = data;
|
fcluster->data_addr = data;
|
||||||
fcluster->meta_addr = meta;
|
fcluster->meta_addr = meta;
|
||||||
fcluster->version = data32[0];
|
fcluster->version = data32[0];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_flash_cluster_data(): handle generic data flash cluster
|
/* _fygue_flash_cluster_data(): handle generic data flash cluster
|
||||||
|
@ -201,51 +201,51 @@ static int _fygue_flash_cluster_details(
|
||||||
* flash cluster data (0x11 or 0x88) are handled in the same way between
|
* flash cluster data (0x11 or 0x88) are handled in the same way between
|
||||||
* all device */
|
* all device */
|
||||||
static int _fygue_flash_cluster_data(
|
static int _fygue_flash_cluster_data(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cluster *fcluster,
|
struct fygue_flash_cluster *fcluster,
|
||||||
int fcluster_id,
|
int fcluster_id,
|
||||||
int fsector_id,
|
int fsector_id,
|
||||||
int fcluster_off
|
int fcluster_off
|
||||||
) {
|
) {
|
||||||
GAUTOTYPE geometry = &(flash->geometry);
|
GAUTOTYPE geometry = &(flash->geometry);
|
||||||
uintptr_t meta;
|
uintptr_t meta;
|
||||||
uintptr_t data;
|
uintptr_t data;
|
||||||
|
|
||||||
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
|
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
|
||||||
data = (
|
data = (
|
||||||
(geometry->phy_start | 0xa0000000) +
|
(geometry->phy_start | 0xa0000000) +
|
||||||
(fsector_id * 0x10000) +
|
(fsector_id * 0x10000) +
|
||||||
(fcluster_off * (8 * 512))
|
(fcluster_off * (8 * 512))
|
||||||
);
|
);
|
||||||
meta = (
|
meta = (
|
||||||
(geometry->phy_start | 0xa0000000) +
|
(geometry->phy_start | 0xa0000000) +
|
||||||
(fsector_id * 0x10000) +
|
(fsector_id * 0x10000) +
|
||||||
(0xf000) +
|
(0xf000) +
|
||||||
(fcluster_off * 0x40)
|
(fcluster_off * 0x40)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
data = (
|
data = (
|
||||||
(geometry->phy_start | 0xa0000000) +
|
(geometry->phy_start | 0xa0000000) +
|
||||||
(fsector_id * 0x20000) +
|
(fsector_id * 0x20000) +
|
||||||
(fcluster_off * (8 * 512))
|
(fcluster_off * (8 * 512))
|
||||||
);
|
);
|
||||||
meta = (
|
meta = (
|
||||||
(geometry->phy_start | 0xa0000000) +
|
(geometry->phy_start | 0xa0000000) +
|
||||||
(fsector_id * 0x20000) +
|
(fsector_id * 0x20000) +
|
||||||
(0x1f000) +
|
(0x1f000) +
|
||||||
(fcluster_off * 0x40)
|
(fcluster_off * 0x40)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0)
|
if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
fcluster->data_addr = data;
|
fcluster->data_addr = data;
|
||||||
fcluster->meta_addr = meta;
|
fcluster->meta_addr = meta;
|
||||||
fcluster->fcluster_id = fcluster_id;
|
fcluster->fcluster_id = fcluster_id;
|
||||||
fcluster->fcluster_id_bfile = (
|
fcluster->fcluster_id_bfile = (
|
||||||
(fsector_id * (geometry->fcluster_per_fsector - 1)) +
|
(fsector_id * (geometry->fcluster_per_fsector - 1)) +
|
||||||
(fcluster_off)
|
(fcluster_off)
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -257,43 +257,43 @@ static int _fygue_flash_cluster_data(
|
||||||
* return
|
* return
|
||||||
* -1 if the provided `fline` is not valid
|
* -1 if the provided `fline` is not valid
|
||||||
* -2 if the provided `fline` have invalid Bfile metadata
|
* -2 if the provided `fline` have invalid Bfile metadata
|
||||||
* 0 if the meta information has been generated */
|
* 0 if the meta information has been generated */
|
||||||
int fygue_flash_cluster_get(
|
int fygue_flash_cluster_get(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cluster *fcluster,
|
struct fygue_flash_cluster *fcluster,
|
||||||
int fcluster_id
|
int fcluster_id
|
||||||
) {
|
) {
|
||||||
GAUTOTYPE geometry = &(flash->geometry);
|
GAUTOTYPE geometry = &(flash->geometry);
|
||||||
int fsector_id;
|
int fsector_id;
|
||||||
int fcluster_off;
|
int fcluster_off;
|
||||||
int nb_entry;
|
int nb_entry;
|
||||||
|
|
||||||
if (flash == NULL || fcluster == NULL)
|
if (flash == NULL || fcluster == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (fcluster_id >= flash->geometry.fcluster_count)
|
if (fcluster_id >= flash->geometry.fcluster_count)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
|
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
|
||||||
nb_entry = 16;
|
nb_entry = 16;
|
||||||
fsector_id = fcluster_id / 16;
|
fsector_id = fcluster_id / 16;
|
||||||
fcluster_off = fcluster_id % 16;
|
fcluster_off = fcluster_id % 16;
|
||||||
} else {
|
} else {
|
||||||
nb_entry = 32;
|
nb_entry = 32;
|
||||||
fsector_id = fcluster_id / 32;
|
fsector_id = fcluster_id / 32;
|
||||||
fcluster_off = fcluster_id % 32;
|
fcluster_off = fcluster_id % 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcluster_off == 0)
|
if (fcluster_off == 0)
|
||||||
return _fygue_flash_cluster_details(flash, fcluster, fsector_id);
|
return _fygue_flash_cluster_details(flash, fcluster, fsector_id);
|
||||||
if (fcluster_off == (nb_entry - 1))
|
if (fcluster_off == (nb_entry - 1))
|
||||||
return _fygue_flash_cluster_meta(flash, fcluster, fsector_id);
|
return _fygue_flash_cluster_meta(flash, fcluster, fsector_id);
|
||||||
return _fygue_flash_cluster_data(
|
return _fygue_flash_cluster_data(
|
||||||
flash,
|
flash,
|
||||||
fcluster,
|
fcluster,
|
||||||
fcluster_id,
|
fcluster_id,
|
||||||
fsector_id,
|
fsector_id,
|
||||||
fcluster_off
|
fcluster_off
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_flash_cluster_geometry() - get geometry information
|
/* fygue_flash_cluster_geometry() - get geometry information
|
||||||
|
@ -304,28 +304,28 @@ int fygue_flash_cluster_get(
|
||||||
* that ignore the last entry which contain meta information
|
* that ignore the last entry which contain meta information
|
||||||
*
|
*
|
||||||
* returns
|
* returns
|
||||||
* -1 if the provided address is not valid
|
* -1 if the provided address is not valid
|
||||||
* 0 success */
|
* 0 success */
|
||||||
int fygue_flash_cluster_geometry(
|
int fygue_flash_cluster_geometry(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
uintptr_t addr,
|
uintptr_t addr,
|
||||||
uint16_t *fcluster_id,
|
uint16_t *fcluster_id,
|
||||||
uint16_t *fsector_id,
|
uint16_t *fsector_id,
|
||||||
uint16_t *fcluster_off
|
uint16_t *fcluster_off
|
||||||
) {
|
) {
|
||||||
int nb_cluster;
|
int nb_cluster;
|
||||||
|
|
||||||
if ((addr & 0x0fffffff) < flash->geometry.phy_start)
|
if ((addr & 0x0fffffff) < flash->geometry.phy_start)
|
||||||
return -1;
|
return -1;
|
||||||
nb_cluster = flash->geometry.fcluster_per_fsector;
|
nb_cluster = flash->geometry.fcluster_per_fsector;
|
||||||
addr = (addr & 0x0fffffff) - flash->geometry.phy_start;
|
addr = (addr & 0x0fffffff) - flash->geometry.phy_start;
|
||||||
if (fcluster_id != NULL) {
|
if (fcluster_id != NULL) {
|
||||||
*fcluster_id = ((addr & 0xfffe0000) >> 17) * nb_cluster;
|
*fcluster_id = ((addr & 0xfffe0000) >> 17) * nb_cluster;
|
||||||
*fcluster_id += ((addr & 0x0001ffff) >> 12);
|
*fcluster_id += ((addr & 0x0001ffff) >> 12);
|
||||||
}
|
}
|
||||||
if (fsector_id != NULL)
|
if (fsector_id != NULL)
|
||||||
*fsector_id = ((addr & 0xfffe0000) >> 17) * nb_cluster;
|
*fsector_id = ((addr & 0xfffe0000) >> 17) * nb_cluster;
|
||||||
if (fcluster_off != NULL)
|
if (fcluster_off != NULL)
|
||||||
*fcluster_off = ((addr & 0x0001ffff) >> 12);
|
*fcluster_off = ((addr & 0x0001ffff) >> 12);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** fygue/flash/cmap - flash cluster map
|
** fygue/flash/cmap - flash cluster map
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -25,89 +25,89 @@
|
||||||
*
|
*
|
||||||
* return
|
* return
|
||||||
* -1 if the provided information is not valid
|
* -1 if the provided information is not valid
|
||||||
* 0 if the provided lcluster exists and has not been updated
|
* 0 if the provided lcluster exists and has not been updated
|
||||||
* 1 if the provided lcluster has been created
|
* 1 if the provided lcluster has been created
|
||||||
* 2 if the provided lcluster exists and has been updated */
|
* 2 if the provided lcluster exists and has been updated */
|
||||||
static int fygue_flash_cmap_update(
|
static int fygue_flash_cmap_update(
|
||||||
struct fygue_flash_cmap *cmap,
|
struct fygue_flash_cmap *cmap,
|
||||||
struct fygue_flash_cluster *fcluster
|
struct fygue_flash_cluster *fcluster
|
||||||
) {
|
) {
|
||||||
struct fygue_flash_cmap_entry *entry;
|
struct fygue_flash_cmap_entry *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (cmap == NULL || fcluster == NULL)
|
if (cmap == NULL || fcluster == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (fcluster->kind != 0x11)
|
if (fcluster->kind != 0x11)
|
||||||
return -1;
|
return -1;
|
||||||
if (cmap->lcluster_id_max > fcluster->lcluster_id)
|
if (cmap->lcluster_id_max > fcluster->lcluster_id)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
cmap->lcluster[fcluster->lcluster_id].version != 0xffffffff &&
|
cmap->lcluster[fcluster->lcluster_id].version != 0xffffffff &&
|
||||||
cmap->lcluster[fcluster->lcluster_id].version
|
cmap->lcluster[fcluster->lcluster_id].version
|
||||||
< fcluster->version
|
< fcluster->version
|
||||||
) {
|
) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cmap->lcluster = reallocarray(
|
cmap->lcluster = reallocarray(
|
||||||
cmap->lcluster,
|
cmap->lcluster,
|
||||||
(fcluster->lcluster_id + 1),
|
(fcluster->lcluster_id + 1),
|
||||||
sizeof(struct fygue_flash_cmap_entry)
|
sizeof(struct fygue_flash_cmap_entry)
|
||||||
);
|
);
|
||||||
for (
|
for (
|
||||||
i = cmap->lcluster_id_max ;
|
i = cmap->lcluster_id_max ;
|
||||||
i < fcluster->lcluster_id ;
|
i < fcluster->lcluster_id ;
|
||||||
i++
|
i++
|
||||||
) {
|
) {
|
||||||
cmap->lcluster[i].fcluster_id = 0xffff;
|
cmap->lcluster[i].fcluster_id = 0xffff;
|
||||||
cmap->lcluster[i].fcluster_id_bfile = 0xffff;
|
cmap->lcluster[i].fcluster_id_bfile = 0xffff;
|
||||||
cmap->lcluster[i].fcluster_addr = 0xffffffff;
|
cmap->lcluster[i].fcluster_addr = 0xffffffff;
|
||||||
cmap->lcluster[i].version = 0xffffffff;
|
cmap->lcluster[i].version = 0xffffffff;
|
||||||
}
|
}
|
||||||
cmap->lcluster_id_max = fcluster->lcluster_id + 1;
|
cmap->lcluster_id_max = fcluster->lcluster_id + 1;
|
||||||
}
|
}
|
||||||
entry = &(cmap->lcluster[fcluster->lcluster_id]);
|
entry = &(cmap->lcluster[fcluster->lcluster_id]);
|
||||||
entry->fcluster_id = fcluster->fcluster_id;
|
entry->fcluster_id = fcluster->fcluster_id;
|
||||||
entry->fcluster_id_bfile = fcluster->fcluster_id_bfile;
|
entry->fcluster_id_bfile = fcluster->fcluster_id_bfile;
|
||||||
entry->fcluster_addr = fcluster->data_addr;
|
entry->fcluster_addr = fcluster->data_addr;
|
||||||
entry->version = fcluster->version;
|
entry->version = fcluster->version;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_flash_cmap_discover(): discover flash information */
|
/* _fygue_flash_cmap_discover(): discover flash information */
|
||||||
static int _fygue_flash_cmap_discover(
|
static int _fygue_flash_cmap_discover(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap
|
struct fygue_flash_cmap *cmap
|
||||||
) {
|
) {
|
||||||
struct fygue_flash_cluster fcluster;
|
struct fygue_flash_cluster fcluster;
|
||||||
int fsector_id;
|
int fsector_id;
|
||||||
int fsector;
|
int fsector;
|
||||||
int rc;
|
int rc;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
fsector_id = 0;
|
fsector_id = 0;
|
||||||
for (
|
for (
|
||||||
fsector = 0 ;
|
fsector = 0 ;
|
||||||
fsector < flash->geometry.fsector_count ;
|
fsector < flash->geometry.fsector_count ;
|
||||||
fsector++
|
fsector++
|
||||||
) {
|
) {
|
||||||
if (fsector != 0)
|
if (fsector != 0)
|
||||||
fsector_id += flash->geometry.fcluster_per_fsector;
|
fsector_id += flash->geometry.fcluster_per_fsector;
|
||||||
if (fygue_flash_cluster_get(flash, &fcluster, fsector_id) != 0)
|
if (fygue_flash_cluster_get(flash, &fcluster, fsector_id) != 0)
|
||||||
continue;
|
continue;
|
||||||
if (fcluster.kind != 0x22)
|
if (fcluster.kind != 0x22)
|
||||||
continue;
|
continue;
|
||||||
for (j = 1 ; j < (flash->geometry.fcluster_per_fsector - 1) ; j++)
|
for (j = 1 ; j < (flash->geometry.fcluster_per_fsector - 1) ; j++)
|
||||||
{
|
{
|
||||||
rc = fygue_flash_cluster_get(flash, &fcluster, fsector_id + j);
|
rc = fygue_flash_cluster_get(flash, &fcluster, fsector_id + j);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
continue;
|
continue;
|
||||||
if (fcluster.kind != 0x11)
|
if (fcluster.kind != 0x11)
|
||||||
continue;
|
continue;
|
||||||
fygue_flash_cmap_update(cmap, &fcluster);
|
fygue_flash_cmap_update(cmap, &fcluster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -116,29 +116,29 @@ static int _fygue_flash_cmap_discover(
|
||||||
|
|
||||||
/* fygue_flash_cmap_lsector_get_addr() - get logical sector address */
|
/* fygue_flash_cmap_lsector_get_addr() - get logical sector address */
|
||||||
int fygue_flash_cmap_lsector_get_addr(
|
int fygue_flash_cmap_lsector_get_addr(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap,
|
struct fygue_flash_cmap *cmap,
|
||||||
uintptr_t *sector,
|
uintptr_t *sector,
|
||||||
uint16_t lsector_id
|
uint16_t lsector_id
|
||||||
) {
|
) {
|
||||||
uintptr_t fsector_addr;
|
uintptr_t fsector_addr;
|
||||||
uint16_t lcluster_id;
|
uint16_t lcluster_id;
|
||||||
|
|
||||||
if (flash == NULL || sector == NULL || cmap == NULL)
|
if (flash == NULL || sector == NULL || cmap == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (cmap->lcluster == NULL)
|
if (cmap->lcluster == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
lcluster_id = lsector_id / 8;
|
lcluster_id = lsector_id / 8;
|
||||||
if (
|
if (
|
||||||
cmap->lcluster_id_max < lcluster_id ||
|
cmap->lcluster_id_max < lcluster_id ||
|
||||||
cmap->lcluster[lcluster_id].fcluster_id == 0xffff
|
cmap->lcluster[lcluster_id].fcluster_id == 0xffff
|
||||||
) {
|
) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
fsector_addr = cmap->lcluster[lcluster_id].fcluster_addr;
|
fsector_addr = cmap->lcluster[lcluster_id].fcluster_addr;
|
||||||
fsector_addr += (lsector_id % 8) * 512;
|
fsector_addr += (lsector_id % 8) * 512;
|
||||||
*sector = fsector_addr;
|
*sector = fsector_addr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_flash_cmap_init() - initialize fcluster translation
|
/* fygue_flash_cmap_init() - initialize fcluster translation
|
||||||
|
@ -149,41 +149,41 @@ int fygue_flash_cmap_lsector_get_addr(
|
||||||
* (read,write,erase). This because the Flash used in recent devices use
|
* (read,write,erase). This because the Flash used in recent devices use
|
||||||
* sector of 128ko which imply, when you want to update one byte of
|
* sector of 128ko which imply, when you want to update one byte of
|
||||||
* memory, you need to:
|
* memory, you need to:
|
||||||
* - copy the whole page in RAM
|
* - copy the whole page in RAM
|
||||||
* - perform the modification
|
* - perform the modification
|
||||||
* - write the new page information
|
* - write the new page information
|
||||||
*
|
*
|
||||||
* So, todo
|
* So, todo
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* -1 if the sector 0 is not found
|
* -1 if the sector 0 is not found
|
||||||
* 0 success */
|
* 0 success */
|
||||||
int fygue_flash_cmap_initialize(
|
int fygue_flash_cmap_initialize(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap
|
struct fygue_flash_cmap *cmap
|
||||||
) {
|
) {
|
||||||
if (flash == NULL || cmap == NULL)
|
if (flash == NULL || cmap == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
memset(cmap, 0x00, sizeof(struct fygue_flash_cmap));
|
memset(cmap, 0x00, sizeof(struct fygue_flash_cmap));
|
||||||
if (_fygue_flash_cmap_discover(flash, cmap) != 0)
|
if (_fygue_flash_cmap_discover(flash, cmap) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (cmap->lcluster == NULL)
|
if (cmap->lcluster == NULL)
|
||||||
return -2;
|
return -2;
|
||||||
if (cmap->lcluster[0].fcluster_id == 0xffff)
|
if (cmap->lcluster[0].fcluster_id == 0xffff)
|
||||||
return -3;
|
return -3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_flash_cmap_sync() - sync the fcluster redirection map */
|
/* fygue_flash_cmap_sync() - sync the fcluster redirection map */
|
||||||
int fygue_flash_cmap_sync(
|
int fygue_flash_cmap_sync(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap
|
struct fygue_flash_cmap *cmap
|
||||||
) {
|
) {
|
||||||
if (flash == NULL || cmap == NULL)
|
if (flash == NULL || cmap == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
for (int i = 0 ; i < cmap->lcluster_id_max ; i++)
|
for (int i = 0 ; i < cmap->lcluster_id_max ; i++)
|
||||||
cmap->lcluster[i].version = 0xffffffff;
|
cmap->lcluster[i].version = 0xffffffff;
|
||||||
if (_fygue_flash_cmap_discover(flash, cmap) != 0)
|
if (_fygue_flash_cmap_discover(flash, cmap) != 0)
|
||||||
return -2;
|
return -2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,45 +16,45 @@
|
||||||
* hardcoded information */
|
* hardcoded information */
|
||||||
int _fygue_flash_hw_detect(struct fygue_flash *flash)
|
int _fygue_flash_hw_detect(struct fygue_flash *flash)
|
||||||
{
|
{
|
||||||
GAUTOTYPE geometry = &(flash->geometry);
|
GAUTOTYPE geometry = &(flash->geometry);
|
||||||
|
|
||||||
switch (gint[HWCALC])
|
switch (gint[HWCALC])
|
||||||
{
|
{
|
||||||
case HWCALC_FXCP400:
|
case HWCALC_FXCP400:
|
||||||
geometry->phy_start = 0x01a20000;
|
geometry->phy_start = 0x01a20000;
|
||||||
geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
|
geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
|
||||||
geometry->fsector_count = 0xf2;
|
geometry->fsector_count = 0xf2;
|
||||||
break;
|
break;
|
||||||
case HWCALC_G35PE2:
|
case HWCALC_G35PE2:
|
||||||
geometry->phy_start = 0x003f0000;
|
geometry->phy_start = 0x003f0000;
|
||||||
geometry->fsector_size = FYGUE_FSECTOR_SIZE_64K;
|
geometry->fsector_size = FYGUE_FSECTOR_SIZE_64K;
|
||||||
geometry->fsector_count = 0x41;
|
geometry->fsector_count = 0x41;
|
||||||
break;
|
break;
|
||||||
case HWCALC_FXCG50:
|
case HWCALC_FXCG50:
|
||||||
geometry->phy_start = 0x00c80000;
|
geometry->phy_start = 0x00c80000;
|
||||||
geometry->fsector_count = 0x9c;
|
geometry->fsector_count = 0x9c;
|
||||||
geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
|
geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
|
||||||
break;
|
break;
|
||||||
case HWCALC_FXCG100:
|
case HWCALC_FXCG100:
|
||||||
geometry->phy_start = 0x00c80000;
|
geometry->phy_start = 0x00c80000;
|
||||||
geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
|
geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
|
||||||
geometry->fsector_count = 0x3d;
|
geometry->fsector_count = 0x3d;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errno = ENOTSUP;
|
errno = ENOTSUP;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_128K) {
|
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_128K) {
|
||||||
geometry->size = geometry->fsector_count * 0x20000;
|
geometry->size = geometry->fsector_count * 0x20000;
|
||||||
geometry->fcluster_count = geometry->fsector_count * 32;
|
geometry->fcluster_count = geometry->fsector_count * 32;
|
||||||
geometry->fcluster_per_fsector = 32;
|
geometry->fcluster_per_fsector = 32;
|
||||||
} else {
|
} else {
|
||||||
geometry->size = geometry->fsector_count * 0x10000;
|
geometry->size = geometry->fsector_count * 0x10000;
|
||||||
geometry->fcluster_count = geometry->fsector_count * 16;
|
geometry->fcluster_count = geometry->fsector_count * 16;
|
||||||
geometry->fcluster_per_fsector = 16;
|
geometry->fcluster_per_fsector = 16;
|
||||||
}
|
}
|
||||||
geometry->phy_end = geometry->phy_start + geometry->size;
|
geometry->phy_end = geometry->phy_start + geometry->size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -64,22 +64,22 @@ int _fygue_flash_hw_detect(struct fygue_flash *flash)
|
||||||
/* fygue_flash_initialize(): init flash abstraction */
|
/* fygue_flash_initialize(): init flash abstraction */
|
||||||
int fygue_flash_initialize(struct fygue_flash *flash)
|
int fygue_flash_initialize(struct fygue_flash *flash)
|
||||||
{
|
{
|
||||||
if (flash == NULL)
|
if (flash == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
memset(flash, 0x00, sizeof(struct fygue_flash));
|
memset(flash, 0x00, sizeof(struct fygue_flash));
|
||||||
if (_fygue_flash_hw_detect(flash) != 0)
|
if (_fygue_flash_hw_detect(flash) != 0)
|
||||||
return -2;
|
return -2;
|
||||||
if (fygue_flash_cmap_initialize(flash, &(flash->cmap)) != 0)
|
if (fygue_flash_cmap_initialize(flash, &(flash->cmap)) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_flash_sync(): re-init flash information */
|
/* fygue_flash_sync(): re-init flash information */
|
||||||
int fygue_flash_sync(struct fygue_flash *flash)
|
int fygue_flash_sync(struct fygue_flash *flash)
|
||||||
{
|
{
|
||||||
if (flash == NULL)
|
if (flash == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (fygue_flash_cmap_sync(flash, &(flash->cmap)) != 0)
|
if (fygue_flash_cmap_sync(flash, &(flash->cmap)) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,52 +7,52 @@
|
||||||
/* fygue_fcluster - generic flash cluster information */
|
/* fygue_fcluster - generic flash cluster information */
|
||||||
struct fygue_flash_cluster
|
struct fygue_flash_cluster
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
FYGUE_FCLUSTER_KIND_DATA = 0x11,
|
FYGUE_FCLUSTER_KIND_DATA = 0x11,
|
||||||
FYGUE_FCLUSTER_KIND_FINFO = 0x22,
|
FYGUE_FCLUSTER_KIND_FINFO = 0x22,
|
||||||
FYGUE_FCLUSTER_KIND_DETAILS = 0x88,
|
FYGUE_FCLUSTER_KIND_DETAILS = 0x88,
|
||||||
FYGUE_FCLUSTER_KIND_METADATA = 0x667,
|
FYGUE_FCLUSTER_KIND_METADATA = 0x667,
|
||||||
} kind;
|
} kind;
|
||||||
uint16_t fcluster_id;
|
uint16_t fcluster_id;
|
||||||
uint16_t fcluster_id_bfile;
|
uint16_t fcluster_id_bfile;
|
||||||
uint16_t lcluster_id;
|
uint16_t lcluster_id;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uintptr_t data_addr;
|
uintptr_t data_addr;
|
||||||
uintptr_t meta_addr;
|
uintptr_t meta_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_fcluster_map_entry - cmap list entry */
|
/* fygue_fcluster_map_entry - cmap list entry */
|
||||||
struct fygue_flash_cmap_entry
|
struct fygue_flash_cmap_entry
|
||||||
{
|
{
|
||||||
uint16_t fcluster_id;
|
uint16_t fcluster_id;
|
||||||
uint16_t fcluster_id_bfile;
|
uint16_t fcluster_id_bfile;
|
||||||
uintptr_t fcluster_addr;
|
uintptr_t fcluster_addr;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_cmap_info - Cluster redirection information */
|
/* fygue_cmap_info - Cluster redirection information */
|
||||||
struct fygue_flash_cmap
|
struct fygue_flash_cmap
|
||||||
{
|
{
|
||||||
struct fygue_flash_cmap_entry *lcluster;
|
struct fygue_flash_cmap_entry *lcluster;
|
||||||
int lcluster_id_max;
|
int lcluster_id_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_flash - flash information */
|
/* fygue_flash - flash information */
|
||||||
struct fygue_flash
|
struct fygue_flash
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
uintptr_t phy_start;
|
uintptr_t phy_start;
|
||||||
uintptr_t phy_end;
|
uintptr_t phy_end;
|
||||||
size_t size;
|
size_t size;
|
||||||
enum {
|
enum {
|
||||||
FYGUE_FSECTOR_SIZE_64K,
|
FYGUE_FSECTOR_SIZE_64K,
|
||||||
FYGUE_FSECTOR_SIZE_128K,
|
FYGUE_FSECTOR_SIZE_128K,
|
||||||
} fsector_size;
|
} fsector_size;
|
||||||
int fsector_count;
|
int fsector_count;
|
||||||
int fcluster_per_fsector;
|
int fcluster_per_fsector;
|
||||||
int fcluster_count;
|
int fcluster_count;
|
||||||
} geometry;
|
} geometry;
|
||||||
struct fygue_flash_cmap cmap;
|
struct fygue_flash_cmap cmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -67,9 +67,9 @@ extern int fygue_flash_sync(struct fygue_flash *flash);
|
||||||
|
|
||||||
/* fygue_flash_sector_get_addr(): return the logical sector address */
|
/* fygue_flash_sector_get_addr(): return the logical sector address */
|
||||||
extern int fygue_flash_sector_get_addr(
|
extern int fygue_flash_sector_get_addr(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
uintptr_t *sector_addr,
|
uintptr_t *sector_addr,
|
||||||
uint16_t sector_id
|
uint16_t sector_id
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -78,22 +78,22 @@ extern int fygue_flash_sector_get_addr(
|
||||||
|
|
||||||
/* fygue_flash_cmap_initialize() - initialize the fcluster redirection map */
|
/* fygue_flash_cmap_initialize() - initialize the fcluster redirection map */
|
||||||
extern int fygue_flash_cmap_initialize(
|
extern int fygue_flash_cmap_initialize(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap
|
struct fygue_flash_cmap *cmap
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_flash_cmap_sync() - sync the fcluster redirection map */
|
/* fygue_flash_cmap_sync() - sync the fcluster redirection map */
|
||||||
extern int fygue_flash_cmap_sync(
|
extern int fygue_flash_cmap_sync(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap
|
struct fygue_flash_cmap *cmap
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_flash_cmap_lsector_get_addr() - get logical sector address */
|
/* fygue_flash_cmap_lsector_get_addr() - get logical sector address */
|
||||||
extern int fygue_flash_cmap_lsector_get_addr(
|
extern int fygue_flash_cmap_lsector_get_addr(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cmap *cmap,
|
struct fygue_flash_cmap *cmap,
|
||||||
uintptr_t *sector,
|
uintptr_t *sector,
|
||||||
uint16_t lsector_id
|
uint16_t lsector_id
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -102,18 +102,18 @@ extern int fygue_flash_cmap_lsector_get_addr(
|
||||||
|
|
||||||
/* fygue_flash_cluster_geometry() - get geometry information */
|
/* fygue_flash_cluster_geometry() - get geometry information */
|
||||||
extern int fygue_flash_cluster_geometry(
|
extern int fygue_flash_cluster_geometry(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
uintptr_t addr,
|
uintptr_t addr,
|
||||||
uint16_t *fcluster_id,
|
uint16_t *fcluster_id,
|
||||||
uint16_t *fsector_id,
|
uint16_t *fsector_id,
|
||||||
uint16_t *fcluster_off
|
uint16_t *fcluster_off
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_flash_cluster_get() - get cluster information */
|
/* fygue_flash_cluster_get() - get cluster information */
|
||||||
extern int fygue_flash_cluster_get(
|
extern int fygue_flash_cluster_get(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
struct fygue_flash_cluster *fcluster,
|
struct fygue_flash_cluster *fcluster,
|
||||||
int fcluster_id
|
int fcluster_id
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif /* FS_FYGUE_FLASH_H */
|
#endif /* FS_FYGUE_FLASH_H */
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
/* fygue_flash_sector_get_addr(): return the logical sector address */
|
/* fygue_flash_sector_get_addr(): return the logical sector address */
|
||||||
int fygue_flash_sector_get_addr(
|
int fygue_flash_sector_get_addr(
|
||||||
struct fygue_flash *flash,
|
struct fygue_flash *flash,
|
||||||
uintptr_t *sector_addr,
|
uintptr_t *sector_addr,
|
||||||
uint16_t sector_id
|
uint16_t sector_id
|
||||||
) {
|
) {
|
||||||
if (flash == NULL || sector_addr == NULL)
|
if (flash == NULL || sector_addr == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return fygue_flash_cmap_lsector_get_addr(
|
return fygue_flash_cmap_lsector_get_addr(
|
||||||
flash,
|
flash,
|
||||||
&(flash->cmap),
|
&(flash->cmap),
|
||||||
sector_addr,
|
sector_addr,
|
||||||
sector_id
|
sector_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** fygue/_fat/sector - FAT sector handling
|
** fygue/_fat/sector - FAT sector handling
|
||||||
*/
|
*/
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@
|
||||||
|
|
||||||
/* fygue_fat_sector_get_addr() - get logical sector addr */
|
/* fygue_fat_sector_get_addr() - get logical sector addr */
|
||||||
int fygue_fat_sector_get_addr(
|
int fygue_fat_sector_get_addr(
|
||||||
struct fygue_fat *fat,
|
struct fygue_fat *fat,
|
||||||
uintptr_t *addr,
|
uintptr_t *addr,
|
||||||
int sector
|
int sector
|
||||||
) {
|
) {
|
||||||
if (fat != NULL)
|
if (fat != NULL)
|
||||||
return fygue_flash_sector_get_addr(&(fat->_flash), addr, sector);
|
return fygue_flash_sector_get_addr(&(fat->_flash), addr, sector);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
/* FYGUE_GFDI_CHEK - shorthand for all GFDI prologue */
|
/* FYGUE_GFDI_CHEK - shorthand for all GFDI prologue */
|
||||||
#define FYGUE_GFDI_CHEK(type) \
|
#define FYGUE_GFDI_CHEK(type) \
|
||||||
_fygue_gfdi_ensure_valid(&fsinfo, desc, type)
|
_fygue_gfdi_ensure_valid(&fsinfo, desc, type)
|
||||||
|
|
||||||
/* _fygue_gfdi_ensure_valid(): ensure GFDI validity
|
/* _fygue_gfdi_ensure_valid(): ensure GFDI validity
|
||||||
*
|
*
|
||||||
|
@ -18,31 +18,31 @@
|
||||||
* - auto mount the FS (if needed) and get information
|
* - auto mount the FS (if needed) and get information
|
||||||
* - ensure file sync if needed */
|
* - ensure file sync if needed */
|
||||||
static int _fygue_gfdi_ensure_valid(
|
static int _fygue_gfdi_ensure_valid(
|
||||||
struct fygue_fsinfo **fsinfo,
|
struct fygue_fsinfo **fsinfo,
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
unsigned int type
|
unsigned int type
|
||||||
) {
|
) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if (fsinfo == NULL)
|
if (fsinfo == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (desc == NULL || desc->type != type)
|
if (desc == NULL || desc->type != type)
|
||||||
FYGUE_RET_ERRNO(EBADF);
|
FYGUE_RET_ERRNO(EBADF);
|
||||||
if (fygue_mount(fsinfo) != 0)
|
if (fygue_mount(fsinfo) != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (desc->dirty)
|
if (desc->dirty)
|
||||||
{
|
{
|
||||||
if (desc->type == FYGUE_DESC_TYPE_DIR)
|
if (desc->type == FYGUE_DESC_TYPE_DIR)
|
||||||
rc = fygue_dir_sync(*fsinfo, &(desc->dir));
|
rc = fygue_dir_sync(*fsinfo, &(desc->dir));
|
||||||
if (desc->type == FYGUE_DESC_TYPE_FILE)
|
if (desc->type == FYGUE_DESC_TYPE_FILE)
|
||||||
rc = fygue_file_sync(*fsinfo, &(desc->file));
|
rc = fygue_file_sync(*fsinfo, &(desc->file));
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
desc->dirty = false;
|
desc->dirty = false;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -51,51 +51,51 @@ static int _fygue_gfdi_ensure_valid(
|
||||||
|
|
||||||
/* fygue_gfdi_file_write(): write file */
|
/* fygue_gfdi_file_write(): write file */
|
||||||
static ssize_t fygue_gfdi_file_write(
|
static ssize_t fygue_gfdi_file_write(
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
||||||
return fygue_file_write(fsinfo, &(desc->file), buffer, size);
|
return fygue_file_write(fsinfo, &(desc->file), buffer, size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_gfdi_file_read(): write directory (EISDIR) */
|
/* fygue_gfdi_file_read(): write directory (EISDIR) */
|
||||||
static ssize_t fygue_gfdi_file_read(
|
static ssize_t fygue_gfdi_file_read(
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
||||||
return fygue_file_read(fsinfo, &(desc->file), buffer, size);
|
return fygue_file_read(fsinfo, &(desc->file), buffer, size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_file_lseek(): seek file */
|
/* fygue_file_lseek(): seek file */
|
||||||
static off_t fygue_gfdi_file_lseek(
|
static off_t fygue_gfdi_file_lseek(
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
off_t offset,
|
off_t offset,
|
||||||
int whence
|
int whence
|
||||||
) {
|
) {
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
||||||
return fygue_file_lseek(fsinfo, &(desc->file), offset, whence);
|
return fygue_file_lseek(fsinfo, &(desc->file), offset, whence);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_file_close(): close directory */
|
/* fygue_file_close(): close directory */
|
||||||
static int fygue_gfdi_file_close(struct fygue_descriptor *desc)
|
static int fygue_gfdi_file_close(struct fygue_descriptor *desc)
|
||||||
{
|
{
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_FILE) == 0)
|
||||||
return fygue_file_close(fsinfo, &(desc->file));
|
return fygue_file_close(fsinfo, &(desc->file));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -104,51 +104,51 @@ static int fygue_gfdi_file_close(struct fygue_descriptor *desc)
|
||||||
|
|
||||||
/* fygue_dir_write(): write directory (EISDIR) */
|
/* fygue_dir_write(): write directory (EISDIR) */
|
||||||
ssize_t fygue_gfdi_dir_write(
|
ssize_t fygue_gfdi_dir_write(
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
||||||
return fygue_dir_write(fsinfo, &(desc->dir), buffer, size);
|
return fygue_dir_write(fsinfo, &(desc->dir), buffer, size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_gfdi_dir_read(): readdir */
|
/* fygue_gfdi_dir_read(): readdir */
|
||||||
ssize_t fygue_gfdi_dir_read(
|
ssize_t fygue_gfdi_dir_read(
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
struct dirent **dirent,
|
struct dirent **dirent,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
||||||
return fygue_dir_read(fsinfo, &(desc->dir), dirent, size);
|
return fygue_dir_read(fsinfo, &(desc->dir), dirent, size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_gfdi_dir_lseek(): seek directory */
|
/* fygue_gfdi_dir_lseek(): seek directory */
|
||||||
off_t fygue_gfdi_dir_lseek(
|
off_t fygue_gfdi_dir_lseek(
|
||||||
struct fygue_descriptor *desc,
|
struct fygue_descriptor *desc,
|
||||||
off_t offset,
|
off_t offset,
|
||||||
int whence
|
int whence
|
||||||
) {
|
) {
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
||||||
return fygue_dir_lseek(fsinfo, &(desc->dir), offset, whence);
|
return fygue_dir_lseek(fsinfo, &(desc->dir), offset, whence);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fygue_gfdi_dir_close(): close directory */
|
/* fygue_gfdi_dir_close(): close directory */
|
||||||
int fygue_gfdi_dir_close(struct fygue_descriptor *desc)
|
int fygue_gfdi_dir_close(struct fygue_descriptor *desc)
|
||||||
{
|
{
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
if (FYGUE_GFDI_CHEK(FYGUE_DESC_TYPE_DIR) == 0)
|
||||||
return fygue_dir_close(fsinfo, &(desc->dir));
|
return fygue_dir_close(fsinfo, &(desc->dir));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -157,15 +157,15 @@ int fygue_gfdi_dir_close(struct fygue_descriptor *desc)
|
||||||
|
|
||||||
/* fygue_file_descriptor_type - fygue file descriptor */
|
/* fygue_file_descriptor_type - fygue file descriptor */
|
||||||
const fs_descriptor_type_t fygue_file_descriptor_type = {
|
const fs_descriptor_type_t fygue_file_descriptor_type = {
|
||||||
.read = (void*)&fygue_gfdi_file_read,
|
.read = (void*)&fygue_gfdi_file_read,
|
||||||
.write = (void*)&fygue_gfdi_file_write,
|
.write = (void*)&fygue_gfdi_file_write,
|
||||||
.lseek = (void*)&fygue_gfdi_file_lseek,
|
.lseek = (void*)&fygue_gfdi_file_lseek,
|
||||||
.close = (void*)&fygue_gfdi_file_close,
|
.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_gfdi_dir_read,
|
.read = (void*)&fygue_gfdi_dir_read,
|
||||||
.write = (void*)&fygue_gfdi_dir_write,
|
.write = (void*)&fygue_gfdi_dir_write,
|
||||||
.lseek = (void*)&fygue_gfdi_dir_lseek,
|
.lseek = (void*)&fygue_gfdi_dir_lseek,
|
||||||
.close = (void*)&fygue_gfdi_dir_close,
|
.close = (void*)&fygue_gfdi_dir_close,
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,13 +28,13 @@ extern const fs_descriptor_type_t fygue_dir_descriptor_type;
|
||||||
|
|
||||||
/* helper to set errno and return -1 */
|
/* helper to set errno and return -1 */
|
||||||
#define FYGUE_RET_ERRNO(error) \
|
#define FYGUE_RET_ERRNO(error) \
|
||||||
do { errno = error; return -1; } while(0);
|
do { errno = error; return -1; } while(0);
|
||||||
|
|
||||||
/* fygue_fsinfo: internal fygue FS information */
|
/* fygue_fsinfo: internal fygue FS information */
|
||||||
struct fygue_fsinfo
|
struct fygue_fsinfo
|
||||||
{
|
{
|
||||||
struct fygue_fat fat;
|
struct fygue_fat fat;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_open() - open file or directory */
|
/* fygue_open() - open file or directory */
|
||||||
|
@ -60,35 +60,35 @@ extern int fygue_mount(struct fygue_fsinfo **fsinfo);
|
||||||
/* fygue_file - file information */
|
/* fygue_file - file information */
|
||||||
struct fygue_file
|
struct fygue_file
|
||||||
{
|
{
|
||||||
struct fygue_fat_file fat;
|
struct fygue_fat_file fat;
|
||||||
off_t cursor;
|
off_t cursor;
|
||||||
size_t size;
|
size_t size;
|
||||||
char *path;
|
char *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_dir - directory information */
|
/* fygue_dir - directory information */
|
||||||
struct fygue_dir
|
struct fygue_dir
|
||||||
{
|
{
|
||||||
struct fygue_fat_dir fat;
|
struct fygue_fat_dir fat;
|
||||||
struct dirent **dirent;
|
struct dirent **dirent;
|
||||||
int dirent_idx_max;
|
int dirent_idx_max;
|
||||||
int count;
|
int count;
|
||||||
int pos;
|
int pos;
|
||||||
char *path;
|
char *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* fygue_descriptor - fygue file descriptor */
|
/* fygue_descriptor - fygue file descriptor */
|
||||||
struct fygue_descriptor
|
struct fygue_descriptor
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
FYGUE_DESC_TYPE_FILE,
|
FYGUE_DESC_TYPE_FILE,
|
||||||
FYGUE_DESC_TYPE_DIR,
|
FYGUE_DESC_TYPE_DIR,
|
||||||
} type;
|
} type;
|
||||||
union {
|
union {
|
||||||
struct fygue_file file;
|
struct fygue_file file;
|
||||||
struct fygue_dir dir;
|
struct fygue_dir dir;
|
||||||
};
|
};
|
||||||
bool dirty;
|
bool dirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -97,8 +97,8 @@ struct fygue_descriptor
|
||||||
|
|
||||||
/* fygue_open_resolve() - open file or directory */
|
/* fygue_open_resolve() - open file or directory */
|
||||||
extern int fygue_open_resolve(
|
extern int fygue_open_resolve(
|
||||||
char const *path,
|
char const *path,
|
||||||
struct fygue_descriptor *desc
|
struct fygue_descriptor *desc
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -107,46 +107,46 @@ extern int fygue_open_resolve(
|
||||||
|
|
||||||
/* fygue_dir_open(): directory-specific open */
|
/* fygue_dir_open(): directory-specific open */
|
||||||
extern int fygue_dir_open(
|
extern int fygue_dir_open(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
struct fygue_dir *dir,
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_fat_dir *fat_dir
|
struct fygue_fat_dir *fat_dir
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_dir_read(): directory read implementation */
|
/* fygue_dir_read(): directory read implementation */
|
||||||
extern ssize_t fygue_dir_read(
|
extern ssize_t fygue_dir_read(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
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(
|
extern int fygue_dir_close(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir
|
struct fygue_dir *dir
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_dir_sync(): directory-specific sync */
|
/* fygue_dir_sync(): directory-specific sync */
|
||||||
extern int fygue_dir_sync(
|
extern int fygue_dir_sync(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir
|
struct fygue_dir *dir
|
||||||
);
|
);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -155,46 +155,46 @@ extern int fygue_dir_sync(
|
||||||
|
|
||||||
/* fygue_file_open(): file open */
|
/* fygue_file_open(): file open */
|
||||||
extern int fygue_file_open(
|
extern int fygue_file_open(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
struct fygue_file *file,
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_fat_file *fat_file
|
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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
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(
|
extern int fygue_file_close(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file
|
struct fygue_file *file
|
||||||
);
|
);
|
||||||
|
|
||||||
/* fygue_file_sync(): file-specific sync */
|
/* fygue_file_sync(): file-specific sync */
|
||||||
extern int fygue_file_sync(
|
extern int fygue_file_sync(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file
|
struct fygue_file *file
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -6,22 +6,22 @@
|
||||||
|
|
||||||
/* fygue_dir_close(): close directory */
|
/* fygue_dir_close(): close directory */
|
||||||
int fygue_dir_close(
|
int fygue_dir_close(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir
|
struct fygue_dir *dir
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || dir == NULL)
|
if (fsinfo == NULL || dir == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
fygue_fat_dir_close(&(fsinfo->fat), &(dir->fat));
|
fygue_fat_dir_close(&(fsinfo->fat), &(dir->fat));
|
||||||
if (dir->dirent != NULL)
|
if (dir->dirent != NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0 ; i < dir->count ; i++) {
|
for (int i = 0 ; i < dir->count ; i++) {
|
||||||
if (dir->dirent[i] != NULL)
|
if (dir->dirent[i] != NULL)
|
||||||
free(dir->dirent[i]);
|
free(dir->dirent[i]);
|
||||||
}
|
}
|
||||||
free(dir->dirent);
|
free(dir->dirent);
|
||||||
}
|
}
|
||||||
if (dir->path != NULL)
|
if (dir->path != NULL)
|
||||||
free(dir->path);
|
free(dir->path);
|
||||||
memset(dir, 0x00, sizeof(struct fygue_dir));
|
memset(dir, 0x00, sizeof(struct fygue_dir));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,23 @@
|
||||||
|
|
||||||
/* fygue_dir_lseek(): seek directory */
|
/* fygue_dir_lseek(): seek directory */
|
||||||
off_t fygue_dir_lseek(
|
off_t fygue_dir_lseek(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
struct fygue_dir *dir,
|
||||||
off_t offset,
|
off_t offset,
|
||||||
int whence
|
int whence
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || dir == NULL)
|
if (fsinfo == NULL || dir == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
|
|
||||||
if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END)
|
if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END)
|
||||||
FYGUE_RET_ERRNO(EINVAL);
|
FYGUE_RET_ERRNO(EINVAL);
|
||||||
if(whence == SEEK_CUR)
|
if(whence == SEEK_CUR)
|
||||||
offset += dir->pos;
|
offset += dir->pos;
|
||||||
if(whence == SEEK_END)
|
if(whence == SEEK_END)
|
||||||
offset += dir->count;
|
offset += dir->count;
|
||||||
if(offset < 0 || offset >= dir->count + 1)
|
if(offset < 0 || offset >= dir->count + 1)
|
||||||
FYGUE_RET_ERRNO(EINVAL);
|
FYGUE_RET_ERRNO(EINVAL);
|
||||||
|
|
||||||
dir->pos = offset;
|
dir->pos = offset;
|
||||||
return dir->pos;
|
return dir->pos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,78 +9,78 @@
|
||||||
/* realloc a prepare the internal table */
|
/* realloc a prepare the internal table */
|
||||||
static int _fygue_dir_open_table_realloc(struct fygue_dir *dir)
|
static int _fygue_dir_open_table_realloc(struct fygue_dir *dir)
|
||||||
{
|
{
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
||||||
tmp = reallocarray(
|
tmp = reallocarray(
|
||||||
dir->dirent,
|
dir->dirent,
|
||||||
dir->dirent_idx_max + 16,
|
dir->dirent_idx_max + 16,
|
||||||
sizeof(struct dirent)
|
sizeof(struct dirent)
|
||||||
);
|
);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
FYGUE_RET_ERRNO(ENOMEM);
|
FYGUE_RET_ERRNO(ENOMEM);
|
||||||
dir->dirent = tmp;
|
dir->dirent = tmp;
|
||||||
dir->dirent_idx_max += 16;
|
dir->dirent_idx_max += 16;
|
||||||
for (int i = dir->count ; i < dir->dirent_idx_max ; i++)
|
for (int i = dir->count ; i < dir->dirent_idx_max ; i++)
|
||||||
dir->dirent[i] = NULL;
|
dir->dirent[i] = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free internal table */
|
/* free internal table */
|
||||||
static void _fygue_dir_open_table_free(struct fygue_dir *dir)
|
static void _fygue_dir_open_table_free(struct fygue_dir *dir)
|
||||||
{
|
{
|
||||||
if (dir->dirent == NULL)
|
if (dir->dirent == NULL)
|
||||||
return;
|
return;
|
||||||
for (int i = 0 ; i < dir->dirent_idx_max ; i++) {
|
for (int i = 0 ; i < dir->dirent_idx_max ; i++) {
|
||||||
if (dir->dirent[i] != NULL)
|
if (dir->dirent[i] != NULL)
|
||||||
free(dir->dirent[i]);
|
free(dir->dirent[i]);
|
||||||
}
|
}
|
||||||
free(dir->dirent);
|
free(dir->dirent);
|
||||||
dir->dirent = NULL;
|
dir->dirent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert FAT dirent to dirent */
|
/* convert FAT dirent to dirent */
|
||||||
static int _fygue_dir_open_convert(
|
static int _fygue_dir_open_convert(
|
||||||
struct dirent **dirent,
|
struct dirent **dirent,
|
||||||
struct fygue_fat_dirent *fat_dirent
|
struct fygue_fat_dirent *fat_dirent
|
||||||
) {
|
) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
len = strlen(fat_dirent->name);
|
len = strlen(fat_dirent->name);
|
||||||
*dirent = calloc(1, sizeof(struct dirent) + len + 2);
|
*dirent = calloc(1, sizeof(struct dirent) + len + 2);
|
||||||
if (*dirent == NULL)
|
if (*dirent == NULL)
|
||||||
FYGUE_RET_ERRNO(ENOMEM);
|
FYGUE_RET_ERRNO(ENOMEM);
|
||||||
(*dirent)->d_ino = fat_dirent->cluster_id;
|
(*dirent)->d_ino = fat_dirent->cluster_id;
|
||||||
(*dirent)->d_type = DT_REG;
|
(*dirent)->d_type = DT_REG;
|
||||||
memcpy((*dirent)->d_name, fat_dirent->name, len + 1);
|
memcpy((*dirent)->d_name, fat_dirent->name, len + 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _fygue_dir_open_discover(): discover all dirent */
|
/* _fygue_dir_open_discover(): discover all dirent */
|
||||||
static int _fygue_dir_open_discover(
|
static int _fygue_dir_open_discover(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir
|
struct fygue_dir *dir
|
||||||
) {
|
) {
|
||||||
struct fygue_fat_dirent dirent;
|
struct fygue_fat_dirent dirent;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
rc = fygue_fat_dir_read(&(fsinfo->fat), &(dir->fat), &dirent);
|
rc = fygue_fat_dir_read(&(fsinfo->fat), &(dir->fat), &dirent);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
break;
|
break;
|
||||||
if (dir->count >= dir->dirent_idx_max) {
|
if (dir->count >= dir->dirent_idx_max) {
|
||||||
if (_fygue_dir_open_table_realloc(dir) != 0)
|
if (_fygue_dir_open_table_realloc(dir) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = _fygue_dir_open_convert(&(dir->dirent[dir->count]), &dirent);
|
rc = _fygue_dir_open_convert(&(dir->dirent[dir->count]), &dirent);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
break;
|
break;
|
||||||
dir->count += 1;
|
dir->count += 1;
|
||||||
}
|
}
|
||||||
_fygue_dir_open_table_free(dir);
|
_fygue_dir_open_table_free(dir);
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -90,27 +90,27 @@ static int _fygue_dir_open_discover(
|
||||||
|
|
||||||
/* fygue_dir_open(): directory-specific open */
|
/* fygue_dir_open(): directory-specific open */
|
||||||
int fygue_dir_open(
|
int fygue_dir_open(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
struct fygue_dir *dir,
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_fat_dir *fat_dir
|
struct fygue_fat_dir *fat_dir
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || dir == NULL || path == NULL || fat_dir == NULL)
|
if (fsinfo == NULL || dir == NULL || path == NULL || fat_dir == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memset(dir, 0x00, sizeof(struct fygue_dir));
|
memset(dir, 0x00, sizeof(struct fygue_dir));
|
||||||
dir->path = strdup(path);
|
dir->path = strdup(path);
|
||||||
if (dir->path == NULL)
|
if (dir->path == NULL)
|
||||||
FYGUE_RET_ERRNO(ENOMEM);
|
FYGUE_RET_ERRNO(ENOMEM);
|
||||||
dir->dirent_idx_max = 0;
|
dir->dirent_idx_max = 0;
|
||||||
dir->dirent = NULL;
|
dir->dirent = NULL;
|
||||||
dir->count = 0;
|
dir->count = 0;
|
||||||
dir->pos = 0;
|
dir->pos = 0;
|
||||||
memcpy(&(dir->fat), fat_dir, sizeof(struct fygue_fat_dir));
|
memcpy(&(dir->fat), fat_dir, sizeof(struct fygue_fat_dir));
|
||||||
|
|
||||||
if (_fygue_dir_open_discover(fsinfo, dir) != 0) {
|
if (_fygue_dir_open_discover(fsinfo, dir) != 0) {
|
||||||
free(dir->path);
|
free(dir->path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,20 +7,20 @@
|
||||||
* notes
|
* notes
|
||||||
* - assume that the directory have read permission */
|
* - assume that the directory have read permission */
|
||||||
ssize_t fygue_dir_read(
|
ssize_t fygue_dir_read(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
struct fygue_dir *dir,
|
||||||
struct dirent **dirent,
|
struct dirent **dirent,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || dir == NULL)
|
if (fsinfo == NULL || dir == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (dirent == NULL)
|
if (dirent == NULL)
|
||||||
FYGUE_RET_ERRNO(EFAULT);
|
FYGUE_RET_ERRNO(EFAULT);
|
||||||
if (size < sizeof *dirent)
|
if (size < sizeof *dirent)
|
||||||
FYGUE_RET_ERRNO(EINVAL);
|
FYGUE_RET_ERRNO(EINVAL);
|
||||||
if (dir->pos >= dir->count)
|
if (dir->pos >= dir->count)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
*dirent = dir->dirent[dir->pos];
|
*dirent = dir->dirent[dir->pos];
|
||||||
dir->pos += 1;
|
dir->pos += 1;
|
||||||
return sizeof *dirent;
|
return sizeof *dirent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,55 +4,55 @@
|
||||||
|
|
||||||
/* fygue_dir_sync(): directory-specific sync */
|
/* fygue_dir_sync(): directory-specific sync */
|
||||||
int fygue_dir_sync(
|
int fygue_dir_sync(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir
|
struct fygue_dir *dir
|
||||||
) {
|
) {
|
||||||
struct fygue_fat_descriptor desc;
|
struct fygue_fat_descriptor desc;
|
||||||
int saved_pos;
|
int saved_pos;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* preliminary check */
|
/* preliminary check */
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if (fsinfo == NULL || dir == NULL)
|
if (fsinfo == NULL || dir == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
|
|
||||||
/* update FAT-specific information */
|
/* update FAT-specific information */
|
||||||
//TODO: assume that the first cluster will remain the same ?
|
//TODO: assume that the first cluster will remain the same ?
|
||||||
if (fygue_fat_open(&(fsinfo->fat), dir->path, &desc) != 0)
|
if (fygue_fat_open(&(fsinfo->fat), dir->path, &desc) != 0)
|
||||||
FYGUE_RET_ERRNO(ENOENT);
|
FYGUE_RET_ERRNO(ENOENT);
|
||||||
if (desc.type != FYGUE_FAT_DESC_TYPE_FILE)
|
if (desc.type != FYGUE_FAT_DESC_TYPE_FILE)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
rc = fygue_fat_dir_sync(
|
rc = fygue_fat_dir_sync(
|
||||||
&(fsinfo->fat),
|
&(fsinfo->fat),
|
||||||
&(desc.dir),
|
&(desc.dir),
|
||||||
desc.file.cluster_entry
|
desc.file.cluster_entry
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
|
|
||||||
/* refresh internal information */
|
/* refresh internal information */
|
||||||
//TODO: re-use realloc
|
//TODO: re-use realloc
|
||||||
if (dir->dirent != NULL)
|
if (dir->dirent != NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0 ; i < dir->count ; i++)
|
for (int i = 0 ; i < dir->count ; i++)
|
||||||
{
|
{
|
||||||
if (dir->dirent[i] == NULL)
|
if (dir->dirent[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
free(dir->dirent[i]);
|
free(dir->dirent[i]);
|
||||||
dir->dirent[i] = NULL;
|
dir->dirent[i] = NULL;
|
||||||
}
|
}
|
||||||
free(dir->dirent);
|
free(dir->dirent);
|
||||||
dir->dirent = NULL;
|
dir->dirent = NULL;
|
||||||
dir->count = 0;
|
dir->count = 0;
|
||||||
}
|
}
|
||||||
/* hack to force regenerate the dirent cache */
|
/* hack to force regenerate the dirent cache */
|
||||||
saved_pos = dir->pos;
|
saved_pos = dir->pos;
|
||||||
if (
|
if (
|
||||||
fygue_dir_lseek(fsinfo, dir, 0, SEEK_SET) != 0 ||
|
fygue_dir_lseek(fsinfo, dir, 0, SEEK_SET) != 0 ||
|
||||||
fygue_dir_lseek(fsinfo, dir, saved_pos, SEEK_SET) != 0
|
fygue_dir_lseek(fsinfo, dir, saved_pos, SEEK_SET) != 0
|
||||||
) {
|
) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_dir *dir,
|
struct fygue_dir *dir,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || dir == NULL)
|
if (fsinfo == NULL || dir == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
FYGUE_RET_ERRNO(EFAULT);
|
FYGUE_RET_ERRNO(EFAULT);
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
FYGUE_RET_ERRNO(EISDIR);
|
FYGUE_RET_ERRNO(EISDIR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
|
|
||||||
/* fygue_file_close(): close directory */
|
/* fygue_file_close(): close directory */
|
||||||
int fygue_file_close(
|
int fygue_file_close(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file
|
struct fygue_file *file
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || file == NULL)
|
if (fsinfo == NULL || file == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
fygue_fat_file_close(&(fsinfo->fat), &(file->fat));
|
fygue_fat_file_close(&(fsinfo->fat), &(file->fat));
|
||||||
if (file->path != NULL)
|
if (file->path != NULL)
|
||||||
free(file->path);
|
free(file->path);
|
||||||
memset(file, 0x00, sizeof(struct fygue_file));
|
memset(file, 0x00, sizeof(struct fygue_file));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,26 +2,26 @@
|
||||||
|
|
||||||
/* fygue_file_lseek(): seek file */
|
/* fygue_file_lseek(): seek file */
|
||||||
off_t fygue_file_lseek(
|
off_t fygue_file_lseek(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
struct fygue_file *file,
|
||||||
off_t offset,
|
off_t offset,
|
||||||
int whence
|
int whence
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || file == NULL)
|
if (fsinfo == NULL || file == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END)
|
if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END)
|
||||||
FYGUE_RET_ERRNO(EINVAL);
|
FYGUE_RET_ERRNO(EINVAL);
|
||||||
|
|
||||||
if(whence == SEEK_CUR)
|
if(whence == SEEK_CUR)
|
||||||
offset += file->cursor;
|
offset += file->cursor;
|
||||||
if(whence == SEEK_END)
|
if(whence == SEEK_END)
|
||||||
offset += file->size;
|
offset += file->size;
|
||||||
if(offset < 0 || (unsigned)offset >= file->size + 1)
|
if(offset < 0 || (unsigned)offset >= file->size + 1)
|
||||||
FYGUE_RET_ERRNO(EINVAL);
|
FYGUE_RET_ERRNO(EINVAL);
|
||||||
|
|
||||||
if (fygue_fat_file_seek(&(fsinfo->fat), &(file->fat), offset) != 0)
|
if (fygue_fat_file_seek(&(fsinfo->fat), &(file->fat), offset) != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
|
|
||||||
file->cursor = offset;
|
file->cursor = offset;
|
||||||
return file->cursor;
|
return file->cursor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,20 @@
|
||||||
|
|
||||||
/* fygue_file_open(): file open */
|
/* fygue_file_open(): file open */
|
||||||
int fygue_file_open(
|
int fygue_file_open(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
struct fygue_file *file,
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_fat_file *fat_file
|
struct fygue_fat_file *fat_file
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || file == NULL || path == NULL || fat_file == NULL)
|
if (fsinfo == NULL || file == NULL || path == NULL || fat_file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memset(file, 0x00, sizeof(struct fygue_file));
|
memset(file, 0x00, sizeof(struct fygue_file));
|
||||||
file->path = strdup(path);
|
file->path = strdup(path);
|
||||||
if (file->path == NULL)
|
if (file->path == NULL)
|
||||||
FYGUE_RET_ERRNO(ENOMEM);
|
FYGUE_RET_ERRNO(ENOMEM);
|
||||||
file->cursor = 0;
|
file->cursor = 0;
|
||||||
file->size = fat_file->size;
|
file->size = fat_file->size;
|
||||||
memcpy(&(file->fat), fat_file, sizeof(struct fygue_fat_file));
|
memcpy(&(file->fat), fat_file, sizeof(struct fygue_fat_file));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,24 @@
|
||||||
|
|
||||||
/* fygue_file_read(): read file data */
|
/* fygue_file_read(): read file data */
|
||||||
ssize_t fygue_file_read(
|
ssize_t fygue_file_read(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
struct fygue_file *file,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
|
|
||||||
if (fsinfo == NULL || file == NULL)
|
if (fsinfo == NULL || file == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
FYGUE_RET_ERRNO(EFAULT);
|
FYGUE_RET_ERRNO(EFAULT);
|
||||||
if (file->cursor > 0 && (unsigned)file->cursor >= file->size)
|
if (file->cursor > 0 && (unsigned)file->cursor >= file->size)
|
||||||
return 0;
|
return 0;
|
||||||
if (file->cursor + size >= file->size)
|
if (file->cursor + size >= file->size)
|
||||||
size = file->size - file->cursor;
|
size = file->size - file->cursor;
|
||||||
read = fygue_fat_file_read(&(fsinfo->fat), &(file->fat), buffer, size);
|
read = fygue_fat_file_read(&(fsinfo->fat), &(file->fat), buffer, size);
|
||||||
if (read < 0)
|
if (read < 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
file->cursor += read;
|
file->cursor += read;
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,28 +3,28 @@
|
||||||
|
|
||||||
/* fygue_file_sync(): file-specific sync */
|
/* fygue_file_sync(): file-specific sync */
|
||||||
int fygue_file_sync(
|
int fygue_file_sync(
|
||||||
struct fygue_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file
|
struct fygue_file *file
|
||||||
) {
|
) {
|
||||||
struct fygue_fat_descriptor desc;
|
struct fygue_fat_descriptor desc;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if (fsinfo == NULL || file == NULL)
|
if (fsinfo == NULL || file == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
|
|
||||||
//TODO: assume that the first cluster will remain the same ?
|
//TODO: assume that the first cluster will remain the same ?
|
||||||
if (fygue_fat_open(&(fsinfo->fat), file->path, &desc) != 0)
|
if (fygue_fat_open(&(fsinfo->fat), file->path, &desc) != 0)
|
||||||
FYGUE_RET_ERRNO(ENOENT);
|
FYGUE_RET_ERRNO(ENOENT);
|
||||||
if (desc.type != FYGUE_FAT_DESC_TYPE_FILE)
|
if (desc.type != FYGUE_FAT_DESC_TYPE_FILE)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
rc = fygue_fat_file_sync(
|
rc = fygue_fat_file_sync(
|
||||||
&(fsinfo->fat),
|
&(fsinfo->fat),
|
||||||
&(desc.file),
|
&(desc.file),
|
||||||
desc.file.cluster_entry
|
desc.file.cluster_entry
|
||||||
);
|
);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +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_fsinfo *fsinfo,
|
struct fygue_fsinfo *fsinfo,
|
||||||
struct fygue_file *file,
|
struct fygue_file *file,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t size
|
size_t size
|
||||||
) {
|
) {
|
||||||
if (fsinfo == NULL || file == NULL)
|
if (fsinfo == NULL || file == NULL)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
FYGUE_RET_ERRNO(EFAULT);
|
FYGUE_RET_ERRNO(EFAULT);
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
FYGUE_RET_ERRNO(EROFS);
|
FYGUE_RET_ERRNO(EROFS);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,28 +18,28 @@ static struct fygue_fsinfo *__fygue_fsinfo = NULL;
|
||||||
* - assume that this global is const after initialisation */
|
* - assume that this global is const after initialisation */
|
||||||
int fygue_mount(struct fygue_fsinfo **fsinfo)
|
int fygue_mount(struct fygue_fsinfo **fsinfo)
|
||||||
{
|
{
|
||||||
if (fsinfo == NULL)
|
if (fsinfo == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
*fsinfo = NULL;
|
*fsinfo = NULL;
|
||||||
if (__fygue_fsinfo == NULL)
|
if (__fygue_fsinfo == NULL)
|
||||||
{
|
{
|
||||||
__fygue_fsinfo = calloc(1, sizeof(struct fygue_fsinfo));
|
__fygue_fsinfo = calloc(1, sizeof(struct fygue_fsinfo));
|
||||||
if (__fygue_fsinfo == NULL)
|
if (__fygue_fsinfo == NULL)
|
||||||
return -2;
|
return -2;
|
||||||
if (fygue_fat_initialize(&(__fygue_fsinfo->fat)) != 0)
|
if (fygue_fat_initialize(&(__fygue_fsinfo->fat)) != 0)
|
||||||
{
|
{
|
||||||
free(__fygue_fsinfo);
|
free(__fygue_fsinfo);
|
||||||
__fygue_fsinfo = NULL;
|
__fygue_fsinfo = NULL;
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
__fygue_fsinfo->dirty = false;
|
__fygue_fsinfo->dirty = false;
|
||||||
}
|
}
|
||||||
if (__fygue_fsinfo->dirty)
|
if (__fygue_fsinfo->dirty)
|
||||||
{
|
{
|
||||||
if (fygue_fat_sync(&(__fygue_fsinfo->fat)) != 0)
|
if (fygue_fat_sync(&(__fygue_fsinfo->fat)) != 0)
|
||||||
return -4;
|
return -4;
|
||||||
__fygue_fsinfo->dirty = false;
|
__fygue_fsinfo->dirty = false;
|
||||||
}
|
}
|
||||||
*fsinfo = __fygue_fsinfo;
|
*fsinfo = __fygue_fsinfo;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,71 +17,71 @@
|
||||||
* - automatically mount the filesystem if needed
|
* - automatically mount the filesystem if needed
|
||||||
* - the saved pathname will not be saved in stat */
|
* - the saved pathname will not be saved in stat */
|
||||||
int fygue_open_resolve(
|
int fygue_open_resolve(
|
||||||
char const * const path,
|
char const * const path,
|
||||||
struct fygue_descriptor *desc
|
struct fygue_descriptor *desc
|
||||||
) {
|
) {
|
||||||
struct fygue_fat_descriptor fat_desc;
|
struct fygue_fat_descriptor fat_desc;
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if (path == NULL || desc == NULL)
|
if (path == NULL || desc == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (fygue_mount(&fsinfo) != 0)
|
if (fygue_mount(&fsinfo) != 0)
|
||||||
return -2;
|
return -2;
|
||||||
if (fygue_fat_open(&(fsinfo->fat), path, &fat_desc) != 0)
|
if (fygue_fat_open(&(fsinfo->fat), path, &fat_desc) != 0)
|
||||||
return -3;
|
return -3;
|
||||||
memset(desc, 0x00, sizeof(struct fygue_descriptor));
|
memset(desc, 0x00, sizeof(struct fygue_descriptor));
|
||||||
if (fat_desc.type == FYGUE_FAT_DESC_TYPE_DIR)
|
if (fat_desc.type == FYGUE_FAT_DESC_TYPE_DIR)
|
||||||
{
|
{
|
||||||
desc->type = FYGUE_DESC_TYPE_DIR;
|
desc->type = FYGUE_DESC_TYPE_DIR;
|
||||||
return fygue_dir_open(fsinfo, &(desc->dir), path, &(fat_desc.dir));
|
return fygue_dir_open(fsinfo, &(desc->dir), path, &(fat_desc.dir));
|
||||||
}
|
}
|
||||||
desc->type = FYGUE_DESC_TYPE_FILE;
|
desc->type = FYGUE_DESC_TYPE_FILE;
|
||||||
return fygue_file_open(fsinfo, &(desc->file), path, &fat_desc.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;
|
||||||
fs_descriptor_t gint_desc;
|
fs_descriptor_t gint_desc;
|
||||||
int exists;
|
int exists;
|
||||||
|
|
||||||
/* preliminary checks */
|
/* preliminary checks */
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if ((flags & O_RDWR) || (flags & O_WRONLY))
|
if ((flags & O_RDWR) || (flags & O_WRONLY))
|
||||||
FYGUE_RET_ERRNO(EROFS);
|
FYGUE_RET_ERRNO(EROFS);
|
||||||
|
|
||||||
/* resolve the entry */
|
/* resolve the entry */
|
||||||
exists = fygue_open_resolve(path, &desc);
|
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))))
|
||||||
FYGUE_RET_ERRNO(ENOENT);
|
FYGUE_RET_ERRNO(ENOENT);
|
||||||
|
|
||||||
/* 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)
|
||||||
FYGUE_RET_ERRNO(EROFS);
|
FYGUE_RET_ERRNO(EROFS);
|
||||||
|
|
||||||
/* 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))
|
||||||
FYGUE_RET_ERRNO(EEXIST);
|
FYGUE_RET_ERRNO(EEXIST);
|
||||||
|
|
||||||
/* generate the final file descriptor */
|
/* generate the final file descriptor */
|
||||||
gint_desc.type = &fygue_file_descriptor_type;
|
gint_desc.type = &fygue_file_descriptor_type;
|
||||||
gint_desc.data = calloc(1, sizeof(struct fygue_descriptor));
|
gint_desc.data = calloc(1, sizeof(struct fygue_descriptor));
|
||||||
if (gint_desc.data == NULL)
|
if (gint_desc.data == NULL)
|
||||||
FYGUE_RET_ERRNO(ENOMEM);
|
FYGUE_RET_ERRNO(ENOMEM);
|
||||||
memcpy(gint_desc.data, &desc, sizeof(struct fygue_descriptor));
|
memcpy(gint_desc.data, &desc, sizeof(struct fygue_descriptor));
|
||||||
if (flags & O_DIRECTORY)
|
if (flags & O_DIRECTORY)
|
||||||
{
|
{
|
||||||
if (desc.type != FYGUE_DESC_TYPE_DIR)
|
if (desc.type != FYGUE_DESC_TYPE_DIR)
|
||||||
FYGUE_RET_ERRNO(ENOTDIR);
|
FYGUE_RET_ERRNO(ENOTDIR);
|
||||||
gint_desc.type = &fygue_dir_descriptor_type;
|
gint_desc.type = &fygue_dir_descriptor_type;
|
||||||
}
|
}
|
||||||
return fs_create_descriptor(&gint_desc);
|
return fs_create_descriptor(&gint_desc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,18 +5,18 @@
|
||||||
/* 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_descriptor desc;
|
struct fygue_descriptor desc;
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if (path == NULL || statbuf == NULL)
|
if (path == NULL || statbuf == NULL)
|
||||||
FYGUE_RET_ERRNO(EFAULT);
|
FYGUE_RET_ERRNO(EFAULT);
|
||||||
if (fygue_mount(&fsinfo) != 0)
|
if (fygue_mount(&fsinfo) != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
if (fygue_open_resolve(path, &desc) != 0)
|
if (fygue_open_resolve(path, &desc) != 0)
|
||||||
FYGUE_RET_ERRNO(ENOENT);
|
FYGUE_RET_ERRNO(ENOENT);
|
||||||
if (desc.type == FYGUE_DESC_TYPE_DIR)
|
if (desc.type == FYGUE_DESC_TYPE_DIR)
|
||||||
return fygue_fat_dir_stat(&(fsinfo->fat), &(desc.dir.fat), statbuf);
|
return fygue_fat_dir_stat(&(fsinfo->fat), &(desc.dir.fat), statbuf);
|
||||||
return fygue_fat_file_stat(&(fsinfo->fat), &(desc.file.fat), statbuf);
|
return fygue_fat_file_stat(&(fsinfo->fat), &(desc.file.fat), statbuf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
/* fygue_sync() - request filesystem re-synchronisation */
|
/* fygue_sync() - request filesystem re-synchronisation */
|
||||||
int fygue_sync(void)
|
int fygue_sync(void)
|
||||||
{
|
{
|
||||||
struct fygue_fsinfo *fsinfo;
|
struct fygue_fsinfo *fsinfo;
|
||||||
|
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if (fygue_mount(&fsinfo) != 0)
|
if (fygue_mount(&fsinfo) != 0)
|
||||||
FYGUE_RET_ERRNO(EIO);
|
FYGUE_RET_ERRNO(EIO);
|
||||||
fsinfo->dirty = true;
|
fsinfo->dirty = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
/* fygue_syncfs() - request filesystem re-synchronisation */
|
/* fygue_syncfs() - request filesystem re-synchronisation */
|
||||||
int fygue_syncfs(void *data)
|
int fygue_syncfs(void *data)
|
||||||
{
|
{
|
||||||
struct fygue_descriptor *desc;
|
struct fygue_descriptor *desc;
|
||||||
|
|
||||||
if(gint[HWFS] != HWFS_FUGUE)
|
if(gint[HWFS] != HWFS_FUGUE)
|
||||||
FYGUE_RET_ERRNO(ENOTSUP);
|
FYGUE_RET_ERRNO(ENOTSUP);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
FYGUE_RET_ERRNO(EBADF);
|
FYGUE_RET_ERRNO(EBADF);
|
||||||
desc = data;
|
desc = data;
|
||||||
desc->dirty = true;
|
desc->dirty = true;
|
||||||
fygue_sync();
|
fygue_sync();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ off_t lseek(int fd, off_t offset, int whence)
|
||||||
|
|
||||||
/* No seek function: cannot seek */
|
/* No seek function: cannot seek */
|
||||||
if(d->type->lseek == NULL)
|
if(d->type->lseek == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
/* BFile_Seek() can flush pending IO write operations. Sync Fygue's
|
/* BFile_Seek() can flush pending IO write operations. Sync Fygue's
|
||||||
* descriptor to avoid data corruption */
|
* descriptor to avoid data corruption */
|
||||||
off_t off = d->type->lseek(d->data, offset, whence);
|
off_t off = d->type->lseek(d->data, offset, whence);
|
||||||
if (fs_descriptor_is_fugue(d))
|
if (fs_descriptor_is_fugue(d))
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,6 @@ int mkdir(char const *path, mode_t mode)
|
||||||
{
|
{
|
||||||
/* Standard mkdir() is the Fugue filesystem only */
|
/* Standard mkdir() is the Fugue filesystem only */
|
||||||
int rc = fugue_mkdir(path, mode);
|
int rc = fugue_mkdir(path, mode);
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ int open(char const *path, int flags, ...)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
/* Standard open() use Fugue filesystem if a write operation
|
/* Standard open() use Fugue filesystem if a write operation
|
||||||
* is requested, otherwise use the Fygue filesystem */
|
* is requested, otherwise use the Fygue filesystem */
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
if ((flags & O_WRONLY) || (flags & O_RDWR)) {
|
if ((flags & O_WRONLY) || (flags & O_RDWR)) {
|
||||||
rc = fugue_open(path, flags, mode);
|
rc = fugue_open(path, flags, mode);
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
} else {
|
} else {
|
||||||
rc = fygue_open(path, flags, mode);
|
rc = fygue_open(path, flags, mode);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@ ssize_t read(int fd, void *buf, size_t size)
|
||||||
|
|
||||||
/* No read function: we can't read anything */
|
/* No read function: we can't read anything */
|
||||||
if(d->type->read == NULL)
|
if(d->type->read == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
/* BFile_Read() can flush data in some circumstances, force-sync Fygue */
|
/* BFile_Read() can flush data in some circumstances, force-sync Fygue */
|
||||||
ssize_t rc = d->type->read(d->data, buf, size);
|
ssize_t rc = d->type->read(d->data, buf, size);
|
||||||
if (fs_descriptor_is_fugue(d))
|
if (fs_descriptor_is_fugue(d))
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ int rename(char const *oldpath, char const *newpath)
|
||||||
{
|
{
|
||||||
/* Standard rename() is the Fugue filesystem only */
|
/* Standard rename() is the Fugue filesystem only */
|
||||||
int rc = fugue_rename(oldpath, newpath);
|
int rc = fugue_rename(oldpath, newpath);
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,6 @@ int rmdir(char const *path)
|
||||||
{
|
{
|
||||||
/* Standard rmdir() is the Fugue filesystem only */
|
/* Standard rmdir() is the Fugue filesystem only */
|
||||||
int rc = fugue_rmdir(path);
|
int rc = fugue_rmdir(path);
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
int stat(char const * restrict path, struct stat * restrict statbuf)
|
int stat(char const * restrict path, struct stat * restrict statbuf)
|
||||||
{
|
{
|
||||||
/* Standard stat() is also provided by Fugue, but rely on Casio's
|
/* Standard stat() is also provided by Fugue, but rely on Casio's
|
||||||
* syscall which do not provide all of the information and request
|
* syscall which do not provide all of the information and request
|
||||||
* a world-switch (internally) to works */
|
* a world-switch (internally) to works */
|
||||||
return fygue_stat(path, statbuf);
|
return fygue_stat(path, statbuf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ int unlink(char const *path)
|
||||||
{
|
{
|
||||||
/* Standard unlink() is the Fugue filesystem only */
|
/* Standard unlink() is the Fugue filesystem only */
|
||||||
int rc = fugue_unlink(path);
|
int rc = fugue_unlink(path);
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ ssize_t write(int fd, const void *buf, size_t size)
|
||||||
}
|
}
|
||||||
/* No write function: discard the contents but show no error */
|
/* No write function: discard the contents but show no error */
|
||||||
if(d->type->write == NULL)
|
if(d->type->write == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
/* A special synchronisation must be performed to ensure that all
|
/* A special synchronisation must be performed to ensure that all
|
||||||
* Fygue's descriptor meta information are valid */
|
* Fygue's descriptor meta information are valid */
|
||||||
size = d->type->write(d->data, buf, size);
|
size = d->type->write(d->data, buf, size);
|
||||||
if (fs_descriptor_is_fugue(d))
|
if (fs_descriptor_is_fugue(d))
|
||||||
fs_fygue_sync();
|
fs_fygue_sync();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue