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