156 lines
4.1 KiB
C
156 lines
4.1 KiB
C
#include <string.h>
|
|
|
|
#include "fsctl/fugue.h"
|
|
#include "fsctl/fugue/bits/fat.h"
|
|
#include "fsctl/fugue/dirent.h"
|
|
#include "fsctl/fugue/logger.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_dirent_t *dirent)
|
|
{
|
|
fugue_fs_t fs;
|
|
|
|
if (dirent == NULL)
|
|
return -1;
|
|
if (fs_table_info(&fs, NULL, NULL) != 0)
|
|
return -2;
|
|
return fugue_dirent_init(dirent, &fs);
|
|
}
|
|
|
|
/* fugue_fs_readdir() : readdir-like function */
|
|
int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file)
|
|
{
|
|
struct fugue_fat_dir *dir;
|
|
fugue_dirent_t dirent_backup;
|
|
fugue_logger_t *log;
|
|
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_dirent_t));
|
|
log = dirent->_private.fs._private.logger;
|
|
|
|
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_write(log, "[WARN] opendir: empty dir block\n");
|
|
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_write(
|
|
log,
|
|
"[WARN] %p:opendir: wierd dir block layout\n",
|
|
dir
|
|
);
|
|
}
|
|
file->type = FUGUE_FILE_TYPE_DIR;
|
|
file->size = FAT_LONG(dir->DIR_FileSize);
|
|
return 0;
|
|
|
|
/* removed entry */
|
|
case 0x05:
|
|
case 0xe5:
|
|
fugue_logger_write(
|
|
log,
|
|
"[NOTICE] %p:opendir : removed entry\n",
|
|
dir
|
|
);
|
|
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_LFN:
|
|
fugue_dirent_name_fetch(dirent, file, dir);
|
|
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_write(
|
|
log,
|
|
"[WARN] %p:opendir : KO attr %02x\n",
|
|
dir, dir->DIR_Attr
|
|
);
|
|
error = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* error handling */
|
|
memcpy(dirent, &dirent_backup, sizeof(fugue_dirent_t));
|
|
memset(file, 0x00, sizeof(fugue_file_t));
|
|
return -1;
|
|
}
|
|
|
|
/* fugue_fs_closedir() : closedir-like function */
|
|
int fugue_fs_closedir(fugue_dirent_t *dir)
|
|
{
|
|
if (dir == NULL)
|
|
return -1;
|
|
memset(dir, 0x00, sizeof(fugue_dirent_t));
|
|
dir->current_dir_addr = 0x00000000;
|
|
dir->cluster_addr_start = 0x00000000;
|
|
dir->cluster_addr_end = 0;
|
|
return 0;
|
|
}
|