fygue: support stat for directory and file

This commit is contained in:
Yann MAGNIN 2025-04-05 09:31:38 +02:00
parent 8b5ede80fe
commit bad0dbd5f4
No known key found for this signature in database
GPG key ID: D82629D933EADC59
10 changed files with 227 additions and 16 deletions

View file

@ -263,6 +263,7 @@ set(SOURCES
src/fs/fygue/fygue.c
src/fs/fygue/fygue_open.c
src/fs/fygue/fygue_syncfs.c
src/fs/fygue/fygue_stat.c
src/fs/fygue/fygue_dir_read.c
src/fs/fygue/fygue_dir_lseek.c
src/fs/fygue/fygue_dir_write.c
@ -271,6 +272,8 @@ set(SOURCES
src/fs/fygue/fat/initialize.c
src/fs/fygue/fat/fat_dir_read.c
src/fs/fygue/fat/fat_dir_close.c
src/fs/fygue/fat/fat_dir_stat.c
src/fs/fygue/fat/fat_file_stat.c
src/fs/fygue/fat/resolve.c
src/fs/fygue/fat/sector.c
src/fs/fygue/flash/cluster.c

View file

@ -2,6 +2,7 @@
#define FS_FYGUE_FAT_H 1
#include <gint/defs/types.h>
#include <sys/stat.h>
#include "../flash/flash.h"
@ -17,6 +18,14 @@
| (((x) & 0x000000ff) << 24) \
)
/* FYGUE_FAT_ATTR_* : FAT dirent attribute */
#define FYGUE_FAT_ATTR_READ_ONLY 0x01
#define FYGUE_FAT_ATTR_HIDDEN 0x02
#define FYGUE_FAT_ATTR_SYSTEM 0x04
#define FYGUE_FAT_ATTR_VOLUME 0x08
#define FYGUE_FAT_ATTR_DIRECTORY 0x10
#define FYGUE_FAT_ATTR_ARCHIVE 0x20
/* fygue_fat - fat information */
struct fygue_fat
{
@ -26,6 +35,8 @@ struct fygue_fat
} Type;
int SectorHiddenCount;
int SectorCount;
int SectorSize;
int SectorPerClus;
int ClusterCount;
int TotalCapacity;
int RootEntCount;
@ -47,10 +58,10 @@ struct fygue_fat
struct fygue_fat_dirent
{
char name[256];
int type;
size_t size;
uintptr_t meta_addr;
unsigned int cluster_id;
int attribute;
};
/* fygue_fat_dir - fygue directory information */
@ -65,12 +76,15 @@ struct fygue_fat_dir
uintptr_t dirent_current_addr;
bool end_of_dirent;
bool dirty;
int attribute;
};
/* fygue_fat_file: file information needed to perform IO primitives */
struct fygue_fat_file
{
int todo;
int cluster_entry;
int attribute;
size_t size;
};
/* fygue_fat_resolve: internal resolve information */
@ -99,6 +113,10 @@ extern int fygue_fat_resolve(
struct fygue_fat_resolve *resolve
);
//---
// Directory interface
//---
/* fygue_fat_dir_read(): readdir primitive */
extern int fygue_fat_dir_read(
struct fygue_fat *fat,
@ -112,6 +130,24 @@ extern int fygue_fat_dir_close(
struct fygue_fat_dir *dir
);
/* fygue_fat_dir_stat(): directory stat primitive */
extern int fygue_fat_dir_stat(
struct fygue_fat *fat,
struct fygue_fat_dir *dir,
struct stat *statbuf
);
//---
// File interface
//---
/* fygue_fat_file_stat(): directory stat primitive */
extern int fygue_fat_file_stat(
struct fygue_fat *fat,
struct fygue_fat_file *file,
struct stat *statbuf
);
//---
// Cluster interface
//---

View file

@ -155,7 +155,7 @@ static void _fygue_fat_readdir_dirent_gen(
while (finfo->idx > 0)
current->name[idx++] = finfo->filename[--finfo->idx];
current->name[idx] = 0x00;
current->type = dirent->DIR_Attr;
current->attribute = dirent->DIR_Attr;
current->size = FAT_DWORD(dirent->DIR_FileSize);
current->meta_addr = (uintptr_t)dirent;
current->cluster_id = (

View file

@ -0,0 +1,66 @@
#include <errno.h>
#include "fat.h"
//---
// Internals
//---
/* _get_mode(): get "pseudo" file mode */
static mode_t _get_mode(struct fygue_fat_dir *dir)
{
mode_t mode;
mode = 0777;
if (dir->attribute & FYGUE_FAT_ATTR_READ_ONLY)
mode = 0444;
if (dir->attribute & FYGUE_FAT_ATTR_DIRECTORY)
return mode | S_IFDIR;
return S_IFREG | 0777;
}
/* _get_block_size(): return one cluster size */
static int _get_block_size(struct fygue_fat *fat)
{
return (fat->SectorSize * fat->SectorPerClus);
}
/* _get_block_nb(): count the number of cluster */
static int _get_block_nb(struct fygue_fat *fat, int cluster)
{
int count;
count = 0;
while (fygue_fat_cluster_get_next(fat, &cluster) == 0)
count += 1;
return count;
}
//---
// Public
//---
/* fygue_fat_dir_stat(): directory-specific stat primitive */
int fygue_fat_dir_stat(
struct fygue_fat *fat,
struct fygue_fat_dir *dir,
struct stat *statbuf
) {
if (fat == NULL || dir == NULL || statbuf == NULL) {
errno = EIO;
return -1;
}
statbuf->st_dev = 0; /* not supported */
statbuf->st_ino = dir->cluster_entry;
statbuf->st_mode = _get_mode(dir);
statbuf->st_nlink = 0; /* not supported */
statbuf->st_uid = 0; /* not supported */
statbuf->st_gid = 0; /* not supported */
statbuf->st_rdev = 0; /* not supported */
statbuf->st_size = 0;
statbuf->st_atime = 0; /* not supported */
statbuf->st_mtime = 0; /* not supported */
statbuf->st_ctime = 0; /* not supported */
statbuf->st_blksize = _get_block_size(fat);
statbuf->st_blocks = _get_block_nb(fat, dir->cluster_entry);
return 0;
}

View file

@ -0,0 +1,61 @@
#include <errno.h>
#include "fat.h"
//---
// Internals
//---
/* _get_mode(): get "pseudo" file mode */
static mode_t _get_mode(int attribute)
{
if (attribute & FYGUE_FAT_ATTR_READ_ONLY)
return S_IFDIR | 0444;
return S_IFDIR | 0777;
}
/* _get_block_size(): return one cluster size */
static int _get_block_size(struct fygue_fat *fat)
{
return (fat->SectorSize * fat->SectorPerClus);
}
/* _get_block_nb(): count the number of cluster */
static int _get_block_nb(struct fygue_fat *fat, int cluster)
{
int count;
count = 1;
while (fygue_fat_cluster_get_next(fat, &cluster) == 0)
count += 1;
return count;
}
//---
// Public
//---
/* fygue_fat_file_stat(): directory-specific stat primitive */
int fygue_fat_file_stat(
struct fygue_fat *fat,
struct fygue_fat_file *file,
struct stat *statbuf
) {
if (fat == NULL || file == NULL || statbuf == NULL) {
errno = EIO;
return -1;
}
statbuf->st_dev = 0; /* not supported */
statbuf->st_ino = file->cluster_entry;
statbuf->st_mode = _get_mode(file->attribute);
statbuf->st_nlink = 0; /* not supported */
statbuf->st_uid = 0; /* not supported */
statbuf->st_gid = 0; /* not supported */
statbuf->st_rdev = 0; /* not supported */
statbuf->st_size = file->size;
statbuf->st_atime = 0; /* not supported */
statbuf->st_mtime = 0; /* not supported */
statbuf->st_ctime = 0; /* not supported */
statbuf->st_blksize = _get_block_size(fat);
statbuf->st_blocks = _get_block_nb(fat, file->cluster_entry);
return 0;
}

View file

@ -127,6 +127,8 @@ static int _fygue_fat_configure(struct fygue_fat *fat)
fat->TotalCapacity = DataSec * FAT_WORD(bpb->BPB_BytsPerSec);
fat->RootEntCount = FAT_WORD(bpb->BPB_RootEntCnt);
fat->SectorSize = FAT_WORD(bpb->BPB_BytsPerSec);
fat->SectorPerClus = bpb->BPB_SecPerClus;
// todo : FAT12-specific operation
fat->ClusterCount = FAT_WORD(bpb->BPB_FATSz16);

View file

@ -36,15 +36,18 @@ static int _fygue_dirent_resolve(
struct fygue_fat_dir *dir,
struct fygue_fat_dirent *dirent
) {
int rc;
memset(dir, 0x00, sizeof(struct fygue_fat_dir));
if (dirent == NULL)
{
if (dirent == NULL) {
dir->cluster_entry = 0;
dir->root_dirent_count = fat->RootEntCount;
dir->attribute = FYGUE_FAT_FILE_TYPE_DIR;
} else {
if ((dirent->type & 0x10) == 0x00)
if ((dirent->attribute & FYGUE_FAT_FILE_TYPE_DIR) == 0x00)
return -1;
dir->cluster_entry = dirent->cluster_id;
dir->attribute = FYGUE_FAT_FILE_TYPE_DIR;
dir->root_dirent_count = 0;
}
dir->dirty = false;
@ -52,18 +55,19 @@ static int _fygue_dirent_resolve(
dir->dirent_cursor = 0;
dir->end_of_dirent = false;
dir->cluster_current = dir->cluster_entry;
int rc = fygue_fat_cluster_get_sector(
rc = fygue_fat_cluster_get_sector(
fat,
dir->cluster_current,
&dir->sector_id
);
if (rc != 0)
return -1;
return fygue_fat_sector_get_addr(
return -2;
rc = fygue_fat_sector_get_addr(
fat,
&dir->dirent_current_addr,
dir->sector_id
);
return (rc != 0) ? -3 : 0;
}
/* _fygue_opendir_find() - try to find the directory entry */
@ -90,11 +94,14 @@ static int _fygue_resolve_set(
struct fygue_fat_resolve *resolve,
struct fygue_fat_dirent *dirent
) {
resolve->type = FYGUE_FAT_FILE_TYPE_DIR;
if (_fygue_dirent_resolve(fat, &(resolve->dir), dirent) == 0)
return 0;
if (dirent == NULL || (dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY)) {
resolve->type = FYGUE_FAT_FILE_TYPE_DIR;
return _fygue_dirent_resolve(fat, &(resolve->dir), dirent);
}
resolve->type = FYGUE_FAT_FILE_TYPE_FILE;
// todo: support IO file information
resolve->file.attribute = dirent->attribute;
resolve->file.cluster_entry = dirent->cluster_id;
resolve->file.size = dirent->size;
return 0;
}

View file

@ -55,7 +55,7 @@ int fygue_resolve(char const * const path, struct fygue_resolve *resolve)
return -1;
if (fygue_mount(&fsinfo, true) != 0)
return -2;
if (fygue_fat_resolve(&(fsinfo->fat), path, &fat_resolve) < 0)
if (fygue_fat_resolve(&(fsinfo->fat), path, &fat_resolve) != 0)
return -3;
memset(resolve, 0x00, sizeof(struct fygue_resolve));
if (fat_resolve.type == FYGUE_FAT_FILE_TYPE_FILE)

View file

@ -24,7 +24,7 @@ int fygue_open(char const *path, int flags, GUNUSED mode_t mode)
/* if opening fails and no explicit file creation is required, fail */
if ((exists < 0 && (!(flags & O_CREAT) || (flags & O_DIRECTORY)))) {
errno = ENOENT;
return exists;
return -1;
}
/* if opening fails and the previous check as not returned an error,
@ -32,7 +32,7 @@ int fygue_open(char const *path, int flags, GUNUSED mode_t mode)
* file-system, so, fail */
if (exists < 0) {
errno = EROFS;
return exists;
return -1;
}
/* If the entry exists and O_EXCL was requested, fail.

36
src/fs/fygue/fygue_stat.c Normal file
View file

@ -0,0 +1,36 @@
#include "fygue.h"
#include "fat/fat.h"
/* fygue_stat(): stat primitive */
int fygue_stat(char const * const path, struct stat *statbuf)
{
struct fygue_resolve resolve;
struct fygue_fsinfo *fsinfo;
ENOTSUP_IF_NOT_FYGUE(-1);
if (path == NULL || statbuf == NULL) {
errno = EFAULT;
return -1;
}
if (fygue_mount(&fsinfo, true) != 0) {
errno = EIO;
return -1;
}
if (fygue_resolve(path, &resolve) != 0) {
errno = ENOENT;
return -1;
}
if (resolve.type == FYGUE_FILE_TYPE_DIR) {
fygue_fat_dir_stat(
&(fsinfo->fat),
&(resolve.dir.fat),
statbuf
);
}
return fygue_fat_file_stat(
&(fsinfo->fat),
&(resolve.file.fat),
statbuf
);
}