fygue: support directory lseek,write(error),close

This commit is contained in:
Yann MAGNIN 2025-04-04 11:25:18 +02:00
parent dae0972878
commit 8b5ede80fe
No known key found for this signature in database
GPG key ID: D82629D933EADC59
11 changed files with 215 additions and 41 deletions

View file

@ -264,9 +264,13 @@ set(SOURCES
src/fs/fygue/fygue_open.c src/fs/fygue/fygue_open.c
src/fs/fygue/fygue_syncfs.c src/fs/fygue/fygue_syncfs.c
src/fs/fygue/fygue_dir_read.c src/fs/fygue/fygue_dir_read.c
src/fs/fygue/fygue_dir_lseek.c
src/fs/fygue/fygue_dir_write.c
src/fs/fygue/fygue_dir_close.c
src/fs/fygue/fat/cluster.c src/fs/fygue/fat/cluster.c
src/fs/fygue/fat/initialize.c src/fs/fygue/fat/initialize.c
src/fs/fygue/fat/readdir.c src/fs/fygue/fat/fat_dir_read.c
src/fs/fygue/fat/fat_dir_close.c
src/fs/fygue/fat/resolve.c src/fs/fygue/fat/resolve.c
src/fs/fygue/fat/sector.c src/fs/fygue/fat/sector.c
src/fs/fygue/flash/cluster.c src/fs/fygue/flash/cluster.c

View file

@ -99,13 +99,19 @@ extern int fygue_fat_resolve(
struct fygue_fat_resolve *resolve struct fygue_fat_resolve *resolve
); );
/* fygue_fat_readdir(): readdir primitive */ /* fygue_fat_dir_read(): readdir primitive */
extern int fygue_fat_readdir( 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 */
extern int fygue_fat_dir_close(
struct fygue_fat *fat,
struct fygue_fat_dir *dir
);
//--- //---
// Cluster interface // Cluster interface
//--- //---

View file

@ -0,0 +1,11 @@
#include "fat.h"
/* fygue_fat_dir_close(): closedir primitive */
int fygue_fat_dir_close(struct fygue_fat *fat, struct fygue_fat_dir *dir)
{
if (fat == NULL || dir == NULL)
return -1;
// nothing to do here...
return 0;
}

View file

@ -371,14 +371,14 @@ static int _fygue_readdir_fat_check(struct _fat_info *finfo)
// Public // Public
//--- //---
/* fygue_fat_readdir() - readdir-like primitive /* fygue_fat_dir_read() - readdir-like primitive
* *
* return * return
* -3 no dirent remaning * -3 no dirent remaning
* -2 internal error * -2 internal error
* -1 argument error * -1 argument error
* 0 success */ * 0 success */
int fygue_fat_readdir( 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

View file

@ -76,7 +76,7 @@ static int _fygue_dirent_find(
) { ) {
while (true) while (true)
{ {
if (fygue_fat_readdir(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;

View file

@ -92,7 +92,7 @@ const fs_descriptor_type_t fygue_descriptor_type = {
const fs_descriptor_type_t fygue_dir_descriptor_type = { const fs_descriptor_type_t fygue_dir_descriptor_type = {
.read = (void*)&fygue_dir_read, .read = (void*)&fygue_dir_read,
.write = NULL, .write = (void*)&fygue_dir_write,
.lseek = NULL, .lseek = (void*)&fygue_dir_lseek,
.close = NULL, .close = NULL,
}; };

View file

@ -68,7 +68,9 @@ struct fygue_resolve {
} file; } file;
struct { struct {
struct fygue_fat_dir fat; struct fygue_fat_dir fat;
struct dirent *dirent; struct dirent **dirent;
int count;
int pos;
} dir; } dir;
}; };
}; };
@ -99,6 +101,20 @@ extern int fygue_dir_read(
size_t size size_t size
); );
/* fygue_dir_lseek(): seek directory */
extern off_t fygue_dir_lseek(
struct fygue_descriptor *desc,
off_t offset,
int whence
);
/* fygue_dir_write(): write directory (EISDIR) */
ssize_t fygue_dir_write(
struct fygue_descriptor *desc,
void *buffer,
size_t size
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -0,0 +1,30 @@
#include <stdlib.h>
#include <string.h>
#include "fygue.h"
#include "fat/fat.h"
int fygue_dir_close(struct fygue_descriptor *desc)
{
struct fygue_fsinfo *fsinfo;
ENOTSUP_IF_NOT_FYGUE(-1);
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) {
errno = EBADF;
return -1;
}
if (fygue_mount(&fsinfo, true) != 0) {
errno = EIO;
return -1;
}
fygue_fat_dir_close(&(fsinfo->fat), &desc->resolve.dir.fat);
if (desc->resolve.dir.dirent != NULL)
{
for (int i = 0 ; i < desc->resolve.dir.count ; i++) {
if (desc->resolve.dir.dirent[i] != NULL)
free(desc->resolve.dir.dirent[i]);
}
free(desc->resolve.dir.dirent);
}
memset(desc, 0x00, sizeof(struct fygue_descriptor));
return 0;
}

View file

@ -0,0 +1,45 @@
#include "fygue.h"
//---
// Internals
//---
/* _fygue_dir_discover(): force discover all directory */
static void _fygue_dir_discover(struct fygue_descriptor *desc)
{
struct dirent *ent = NULL;
while (true)
{
if (fygue_dir_read(desc, &ent, sizeof(ent)) != sizeof(ent))
break;
}
}
//---
// Public
//---
/* fygue_dir_lseek(): seek directory */
off_t fygue_dir_lseek(
struct fygue_descriptor *desc,
off_t offset,
int whence
) {
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) {
errno = EBADF;
return -1;
}
if(whence == SEEK_CUR)
offset += desc->resolve.dir.pos;
if(whence == SEEK_END) {
_fygue_dir_discover(desc);
offset += desc->resolve.dir.count;
}
if(offset < 0 || offset >= desc->resolve.dir.count + 1) {
errno = EINVAL;
return -1;
}
desc->resolve.dir.pos = offset;
return desc->resolve.dir.pos;
}

View file

@ -2,6 +2,68 @@
#include <string.h> #include <string.h>
#include "fygue.h" #include "fygue.h"
//---
// Internals
//---
/* _fygue_dir_fat_read(): read and update internal cache
*
* return
* -2 no directory found
* -1 internal error
* 0 success */
static int _fygue_dir_fat_read(
struct fygue_fsinfo *fsinfo,
struct fygue_descriptor *desc
) {
struct fygue_fat_dirent fat_dirent;
struct dirent **dirent;
void *tmp;
size_t len;
int rc;
rc = fygue_fat_dir_read(
&(fsinfo->fat),
&desc->resolve.dir.fat,
&fat_dirent
);
if (rc <= -3)
return -2;
if (rc < 0) {
errno = EIO;
return -1;
}
tmp = reallocarray(
desc->resolve.dir.dirent,
desc->resolve.dir.count + 1,
sizeof(struct dirent *)
);
if (tmp == NULL) {
errno = ENOMEM;
return -1;
}
desc->resolve.dir.dirent = tmp;
desc->resolve.dir.count += 1;
//FIXME: ensure UTF-8/SHIFT-JS
len = strlen(fat_dirent.name);
dirent = &(desc->resolve.dir.dirent[desc->resolve.dir.pos]);
*dirent = calloc(1, sizeof(struct dirent) + len + 2);
if (*dirent == NULL) {
desc->resolve.dir.count -= 1;
errno = ENOMEM;
return -1;
}
//FIXME: ensure UTF-8/SHIFT-JS
(*dirent)->d_ino = fat_dirent.cluster_id;
(*dirent)->d_type = DT_REG;
memcpy((*dirent)->d_name, fat_dirent.name, len + 1);
return 0;
}
//---
// Public
//---
/* fygue_dir_read(): directory read implementation /* fygue_dir_read(): directory read implementation
* *
* notes * notes
@ -11,9 +73,7 @@ int fygue_dir_read(
struct dirent **dirent, struct dirent **dirent,
size_t size size_t size
) { ) {
struct fygue_fat_dirent fat_dirent;
struct fygue_fsinfo *fsinfo; struct fygue_fsinfo *fsinfo;
size_t len;
int rc; int rc;
ENOTSUP_IF_NOT_FYGUE(-1); ENOTSUP_IF_NOT_FYGUE(-1);
@ -34,35 +94,15 @@ int fygue_dir_read(
errno = EIO; errno = EIO;
return -1; return -1;
} }
if (desc->resolve.dir.pos >= desc->resolve.dir.count)
/* get the next FAT dirent */ {
rc = fygue_fat_readdir( rc = _fygue_dir_fat_read(fsinfo, desc);
&(fsinfo->fat), if (rc == -2)
&desc->resolve.dir.fat, return 0;
&fat_dirent if (rc < 0)
); return rc;
if (rc <= -3)
return 0;
if (rc < 0) {
errno = EIO;
return -1;
} }
*dirent = desc->resolve.dir.dirent[desc->resolve.dir.pos];
/* since `struct dirent` use flexible array to store the filename desc->resolve.dir.pos += 1;
* we need to reallocate the buffer each time */ return sizeof *dirent;
//FIXME: ensure UTF-8/SHIFT-JS
len = strlen(fat_dirent.name);
*dirent = desc->resolve.dir.dirent;
*dirent = realloc(*dirent, sizeof(struct dirent) + len + 2);
if (*dirent == NULL) {
errno = ENOMEM;
return -1;
}
/* convert FAT dirent into generic dirent information */
//FIXME: ensure UTF-8/SHIFT-JS
(*dirent)->d_ino = fat_dirent.cluster_id;
(*dirent)->d_type = DT_REG;
memcpy((*dirent)->d_name, fat_dirent.name, len + 1);
return 0;
} }

View file

@ -0,0 +1,22 @@
#include "fygue.h"
/* fygue_dir_write(): write directory (EISDIR) */
ssize_t fygue_dir_write(
struct fygue_descriptor *desc,
void *buffer,
size_t size
) {
ENOTSUP_IF_NOT_FYGUE(-1);
if (desc == NULL || desc->resolve.type != FYGUE_FILE_TYPE_DIR) {
errno = EBADF;
return -1;
}
if (buffer == NULL) {
errno = EFAULT;
return -1;
}
if (size == 0)
return 0;
errno = EISDIR;
return -1;
}