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_syncfs.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/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/sector.c
src/fs/fygue/flash/cluster.c

View file

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

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
//---
/* fygue_fat_readdir() - readdir-like primitive
/* fygue_fat_dir_read() - readdir-like primitive
*
* return
* -3 no dirent remaning
* -2 internal error
* -1 argument error
* 0 success */
int fygue_fat_readdir(
int fygue_fat_dir_read(
struct fygue_fat *fat,
struct fygue_fat_dir *dir,
struct fygue_fat_dirent *current

View file

@ -76,7 +76,7 @@ static int _fygue_dirent_find(
) {
while (true)
{
if (fygue_fat_readdir(fat, dir, dirent) != 0)
if (fygue_fat_dir_read(fat, dir, dirent) != 0)
return -1;
if (strncmp(dirent->name, start, len) != 0)
continue;

View file

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

View file

@ -68,7 +68,9 @@ struct fygue_resolve {
} file;
struct {
struct fygue_fat_dir fat;
struct dirent *dirent;
struct dirent **dirent;
int count;
int pos;
} dir;
};
};
@ -99,6 +101,20 @@ extern int fygue_dir_read(
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
}
#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 "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
*
* notes
@ -11,9 +73,7 @@ int fygue_dir_read(
struct dirent **dirent,
size_t size
) {
struct fygue_fat_dirent fat_dirent;
struct fygue_fsinfo *fsinfo;
size_t len;
int rc;
ENOTSUP_IF_NOT_FYGUE(-1);
@ -34,35 +94,15 @@ int fygue_dir_read(
errno = EIO;
return -1;
}
/* get the next FAT dirent */
rc = fygue_fat_readdir(
&(fsinfo->fat),
&desc->resolve.dir.fat,
&fat_dirent
);
if (rc <= -3)
return 0;
if (rc < 0) {
errno = EIO;
return -1;
if (desc->resolve.dir.pos >= desc->resolve.dir.count)
{
rc = _fygue_dir_fat_read(fsinfo, desc);
if (rc == -2)
return 0;
if (rc < 0)
return rc;
}
/* since `struct dirent` use flexible array to store the filename
* we need to reallocate the buffer each time */
//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;
*dirent = desc->resolve.dir.dirent[desc->resolve.dir.pos];
desc->resolve.dir.pos += 1;
return sizeof *dirent;
}

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