#include <_stdio.h> #include <alloc.h> #include <fileSystem.h> #include <util.h> FileSystemFolder rootFolder = { .name = "/", .type = FS_FOLDER, .children = NULL}; void printFolderTree(FileSystemFolder *folder, char *prefix) { char *nextPrefix = stringCombine(prefix, " "); for (ListElement *current = *folder->children; current; current = current->next) { FileSystemTreeNode *child = current->data; printf("%s%s\n", prefix, child->name); if (child->type == FS_FOLDER) { if (child->name[0] == '.') { continue; } printFolderTree(current->data, nextPrefix); } } free(nextPrefix); } void printFileSystemTree() { printFolderTree(&rootFolder, ""); } void setupFatInfo(FatInfo *info, FatBootSector *boot, HardDrive *hardDrive) { info->bootSector = boot; info->rootDirectorySize = (boot->rootEntryCount * 32 + boot->sectorSize - 1) / boot->sectorSize; info->fatSize = boot->fatSize16Bit ? boot->fatSize16Bit : 0; info->totalSectorCount = boot->totalSectorCount16Bit ? boot->totalSectorCount16Bit : boot->totalSectorCount32Bit; uint32_t dataSectorCount = info->totalSectorCount - (boot->reservedSectorCount + (boot->FATCount * info->fatSize) + info->rootDirectorySize); uint32_t clusterCount = dataSectorCount / boot->sectorsPerCluster; if (clusterCount < 4085) { info->version = 12; } else if (clusterCount < 65525) { info->version = 16; } else { info->version = 32; } info->firstDataSector = boot->reservedSectorCount + (boot->FATCount * info->fatSize) + info->rootDirectorySize; info->firstFatSector = boot->reservedSectorCount; info->firstRootSector = info->firstDataSector - info->rootDirectorySize; info->fat = malloc(info->fatSize * boot->sectorSize); info->hardDrive = hardDrive; hardDrive->access(hardDrive, info->firstFatSector, info->fat, info->fatSize, 0); printf("size: %i\n", info->fatSize * info->bootSector->sectorSize * sizeof(void *) / info->version / 8); info->knownFolders = malloc(info->fatSize * info->bootSector->sectorSize / sizeof(void *) * info->version / 8); } uint32_t getNextCluster(FatInfo *info, uint32_t cluster) { switch (info->version) { case 16: return ((uint16_t *)info->fat)[cluster]; } return 00; } bool isClusterEnd(FatInfo *info, uint32_t cluster) { switch (info->version) { case 16: return cluster == 0xFFFF; } return true; } char *getFullString(LongNameEntry *name) { char *string = malloc(14); string[14] = 0; for (uint8_t i = 0; i < 5; i++) { string[i] = name->name1[i * 2]; } for (uint8_t i = 0; i < 6; i++) { string[5 + i] = name->name2[i * 2]; } for (uint8_t i = 0; i < 2; i++) { string[11 + i] = name->name3[i * 2]; } return string; } char *getCombinedName(ListElement **longName) { char *current = "", *new; while (*longName != NULL) { new = stringCombine(popBeginning(longName), current); if (strlen(current)) { free(current); } current = new; } return current; } char *getName(ListElement **longName, FatDirectoryEntry *directory) { if (listCount(*longName)) { return getCombinedName(longName); } char *name = malloc(12); // 8:3 short name name[11] = 0; for (uint8_t i = 0; i < 11; i++) { name[i] = directory->name[i]; } return name; } uint32_t getClusterSector(FatInfo *info, uint32_t cluster) { return info->firstDataSector + ((cluster - 2) * info->bootSector->sectorsPerCluster); } void folderScanCluster(FatInfo *info, uint32_t cluster, FileSystemFolder *parent); void setupFolder(char *name, FatDirectoryEntry *directory, FatInfo *info, FileSystemFolder *parent) { FileSystemFolder *folder = malloc(sizeof(FileSystemFolder)); folder->name = name; folder->type = FS_FOLDER; uint32_t cluster = directory->firstDataClusterLower | directory->fistDataClusterUpper << 16; listAdd(parent->children, folder); if (info->knownFolders[cluster]) { folder->children = info->knownFolders[cluster]; return; } if (cluster == 0) { folder->children = rootFolder.children; return; } folder->children = malloc(sizeof(ListElement **)); info->knownFolders[cluster] = folder->children; *folder->children = NULL; folderScanCluster(info, getClusterSector(info, cluster), folder); while (!isClusterEnd(info, cluster)) { cluster = getNextCluster(info, cluster); if (cluster > 0xFF00) { return; } folderScanCluster(info, getClusterSector(info, cluster), folder); } } void setupFile(char *name, FileSystemFolder *parent) { FileSystemFile *file = malloc(sizeof(FileSystemFile)); file->name = name; file->type = FS_FILE; file->subType = 0; listAdd(parent->children, file); } void setupChild(char *name, FatDirectoryEntry *directoryEntry, FatInfo *info, FileSystemFolder *parent) { if (directoryEntry->attributes & FAT_ATTRIBUTE_VOLUME_ID) { info->volumeID = name; return; } if (directoryEntry->attributes & FAT_ATTRIBUTE_DIRECTORY) { setupFolder(name, directoryEntry, info, parent); } else { setupFile(name, parent); } } void folderScanCluster(FatInfo *info, uint32_t sector, FileSystemFolder *parent) { void *clusterData = malloc(info->bootSector->sectorSize * info->bootSector->sectorsPerCluster); info->hardDrive->access(info->hardDrive, sector, clusterData, info->bootSector->sectorsPerCluster, 0); FatDirectoryEntry *directory = clusterData; ListElement *longName = NULL; uint32_t i; for (i = 0; i < info->bootSector->sectorSize * info->bootSector->sectorsPerCluster / sizeof(FatDirectoryEntry); i++) { if (directory[i].name[0] == 0) { break; } if (directory[i].name[0] == (char)0xE5 || directory[i].name[0] == (char)0xFF) { continue; } if (directory[i].attributes == FAT_ATTRIBUTE_LONG_NAME) { listAdd(&longName, getFullString((void *)&(directory[i]))); continue; } setupChild(getName(&longName, &directory[i]), &directory[i], info, parent); } listClear(&longName, true); free(clusterData); } void mountDisk(HardDrive *drive) { void *bootSector = malloc(512); drive->access(drive, 0, bootSector, 1, 0); FatBootSector *boot = bootSector; FatInfo *info = malloc(sizeof(FatInfo)); setupFatInfo(info, boot, drive); printf("type: FAT%i\n", info->version); rootFolder.children = malloc(sizeof(ListElement *)); folderScanCluster(info, info->firstRootSector, &rootFolder); }