fsctl/src/fugue/dir.c

145 lines
3.8 KiB
C

#include <string.h>
#include "fsctl/fugue.h"
#include "fsctl/fugue/bits/fat.h"
#include "fsctl/fugue/dirent.h"
#include "fsctl/fugue/utils.h"
#include "fsctl/utils/fs_table.h"
//---
// Internals
//---
//---
// Public
//---
/* fugue_fs_opendir() : opendir-like function */
int fugue_fs_opendir(fugue_dir_t *dir)
{
fugue_fs_t fs;
if (dir == NULL)
return -1;
if (fs_table_info(&fs, NULL, NULL) != 0)
return -2;
memset(dir, 0x00, sizeof(fugue_dir_t));
memcpy(&dir->_private.fs, &fs, sizeof(fugue_fs_t));
dir->current_dir_addr = (uintptr_t)fs._private.root;
dir->cluster_addr = (uintptr_t)fs._private.root;
dir->cluster_size = fs.props.sector_root_nb * 512;
return 0;
}
/* fugue_fs_readdir() : readdir-like function */
int fugue_fs_readdir(fugue_dir_t *dirent, fugue_file_t *file)
{
struct fugue_fat_dir *dir;
fugue_dir_t dirent_backup;
bool error;
bool vfat;
if (dirent == NULL)
return -1;
if (file == NULL)
return -1;
if (dirent->current_dir_addr == 0x00000000)
return -2;
memset(file, 0x00, sizeof(fugue_file_t));
memcpy(&dirent_backup, dirent, sizeof(fugue_dir_t));
vfat = false;
error = false;
while (error == false)
{
/* fetch the current FAT directory and walk */
dir = fugue_dirent_dir_fetch(dirent);
if (dir == NULL) {
error = true;
continue;
}
//---
// handle special name behaviour
//---
switch(dir->DIR_Name[0])
{
/* handle free directory */
case 0x00:
//fugue_logger_warn("opendir: wierd empty directory block ")
error = true;
continue;
/* dot and dotdot special file */
case '.':
if (memcmp(dir->DIR_Name, ". ", 2) == 0)
memcpy(file->name, ".", 2);
if (memcmp(dir->DIR_Name, ".. ", 3) == 0)
memcpy(file->name, "..", 3);
if (vfat == true)
//fugue_logger_warn("opendir: wierd directory block ")
file->type = FUGUE_FILE_TYPE_DIR;
file->size = FAT_LONG(dir->DIR_FileSize);
return 0;
/* removed entry */
case 0x05:
case 0xe5:
//fugue_logger_notice("opendir : removed entry");
memset(file, 0x00, sizeof(fugue_file_t));
vfat = false;
continue;
}
//---
// handle directory attribute
//---
switch(dir->DIR_Attr)
{
/* handle file name fragment */
case FUGUE_DIR_ATTR_VNAME:
fugue_dirent_name_fetch(dirent, file);
vfat = true;
break;
/* file handling */
case FUGUE_DIR_ATTR_RDONLY:
case FUGUE_DIR_ATTR_HIDDEN:
case FUGUE_DIR_ATTR_SYSTEM:
case FUGUE_DIR_ATTR_DIR:
case FUGUE_DIR_ATTR_ARCHIVE:
case FUGUE_DIR_ATTR_DEVICE:
//TODO : file type
file->type = FUGUE_FILE_TYPE_FILE;
file->size = FAT_LONG(dir->DIR_FileSize);
return 0;
/* other attribute not handled */
default:
//fugue_logger_warn("opendir : unsupported attribute ")
error = true;
break;
}
}
/* error handling */
memcpy(dirent, &dirent_backup, sizeof(fugue_dir_t));
memset(file, 0x00, sizeof(fugue_file_t));
return -1;
}
/* fugue_fs_closedir() : closedir-like function */
int fugue_fs_closedir(fugue_dir_t *dir)
{
if (dir == NULL)
return -1;
memset(dir, 0x00, sizeof(fugue_dir_t));
dir->current_dir_addr = 0x00000000;
dir->cluster_addr = 0x00000000;
dir->cluster_size = 0;
return 0;
}