fygue: switch tabs to spaces :)

This commit is contained in:
Yann MAGNIN 2025-04-12 08:47:17 +02:00
parent 817e654e74
commit 7ff93e79f0
No known key found for this signature in database
GPG key ID: D82629D933EADC59
61 changed files with 2094 additions and 2101 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, &sector_id) != 0) if (fygue_fat_cluster_get_sector(fat, cluster_id, &sector_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);
} }

View file

@ -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*)&sector, 0) != 0) if (fygue_fat_sector_get_addr(fat, (void*)&sector, 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;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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