mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-05-18 15:29:16 +02:00
fygue: support directory lseek,write(error),close
This commit is contained in:
parent
dae0972878
commit
8b5ede80fe
11 changed files with 215 additions and 41 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//---
|
||||
|
|
11
src/fs/fygue/fat/fat_dir_close.c
Normal file
11
src/fs/fygue/fat/fat_dir_close.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
30
src/fs/fygue/fygue_dir_close.c
Normal file
30
src/fs/fygue/fygue_dir_close.c
Normal 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;
|
||||
}
|
45
src/fs/fygue/fygue_dir_lseek.c
Normal file
45
src/fs/fygue/fygue_dir_lseek.c
Normal 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;
|
||||
}
|
|
@ -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)
|
||||
if (desc->resolve.dir.pos >= desc->resolve.dir.count)
|
||||
{
|
||||
rc = _fygue_dir_fat_read(fsinfo, desc);
|
||||
if (rc == -2)
|
||||
return 0;
|
||||
if (rc < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
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;
|
||||
}
|
||||
|
|
22
src/fs/fygue/fygue_dir_write.c
Normal file
22
src/fs/fygue/fygue_dir_write.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue