#include #include #include #include #define MAX_FS_COUNT 64 #define BAD 0xffffffff FileSystem* fsArray; uint32 fsCount; MountPoint* mpArray; uint32 mpCount; uint32 mpAllocated; #define LogVfs(...) { Log("%#[Vfs] ", ColorLightBlue); Log(__VA_ARGS__); } #define ErrorVfs(...) { Error("%#[Vfs] ", ColorLightBlue); Error(__VA_ARGS__); } void VfsInstall () { fsArray = (FileSystem*) kmalloc(MAX_FS_COUNT * sizeof(FileSystem)); fsCount = 0; mpArray = (MountPoint*) kmalloc(32 * sizeof(MountPoint)); mpCount = 0; mpAllocated = 32; LogVfs("%#VFS now in business.\n", ColorLightGreen); } uint8 VfsInstallFs (FileSystem* fs) { if (fsCount >= MAX_FS_COUNT) { ErrorVfs("%#Failed to install file system '%s': FS count reached.\n", ColorLightRed, fs->Name); return 0; } memcpy(&fsArray[fsCount], fs, sizeof(FileSystem)); fsArray[fsCount].Id = fsCount; ++fsCount; LogVfs("Installed file system %#.\n", ColorWhite, fs->Name); return 1; } uint32 VfsFindDevice (string dev) { uint32 i; for (i = 0; i < mpCount; i++) if (strcmp(dev, mpArray[i].Name) == 0) return i; return BAD; } // Returns mount point index, removes dev name from path uint32 VfsParsePath (string* path) { // Sanity check if (!path || !(*path)) return BAD; string dev = *path, p = strchr(*path, ':'); if (p == NULL) return BAD; // invalid path // Split string *path = p+1; *p = '\0'; return VfsFindDevice(dev); } uint8 VfsMount (string Name, DevReadRoutine R, DevWriteRoutine W, uint32 BlockSize) { uint32 i, fsId = BAD, mpIndex = BAD; // Try to figure out the file system for (i = 0; i < fsCount && fsId == BAD; i++) if (fsArray->Detect && fsArray->Detect(R, BlockSize)) fsId = i; if (fsId == BAD) { ErrorVfs("%#Failed to mount device %s: no file system found.\n", ColorLightRed, Name) return 0; // No file system, no good } // Try to find an empty slot to fill for (i = 0; i < mpCount && mpIndex == BAD; i++) if (mpArray[i].Id == BAD) mpIndex = i; // No empty slots? if (mpIndex == BAD) { // Make sure we have enough space if (mpCount == mpAllocated) { mpAllocated += 4; mpArray = kmrealloc(mpArray, mpAllocated * sizeof(MountPoint)); } mpIndex = mpCount++; } // Add to mount point list, set up data mpArray[mpIndex].Id = mpIndex; mpArray[mpIndex].FsId = fsId; mpArray[mpIndex].BlockSize = BlockSize; mpArray[mpIndex].Read = R; mpArray[mpIndex].Write = W; // Change name if it already exists uint32 find = VfsFindDevice(Name); if (find != BAD) { uint32 len = strlen(Name); uint8 success = 0; Name[len+1] = '\0'; // Try to find a number index for (find = '0'; find <= '9' && !success; find++) { Name[len] = find; if (VfsFindDevice(Name) == BAD) success = 1; } // What? Haven't found anything yet? Try the alphabet for (find = 'a'; find <= 'z' && !success; find++) { Name[len] = find; if (VfsFindDevice(Name) == BAD) success = 1; } // Still nothing? How in the world is this even possible ?!?!?! if (!success) return 0; } memcpy(mpArray[mpCount].Name, Name, sizeof(char) * 128); LogVfs("Mounted device %#%s", ColorWhite, Name); return 1; } void VfsUnmount (uint32 dev_id) { mpArray[dev_id].Id = BAD; mpCount--; } // Returns pointer to FILE structure that was inputed if success, null otherwise FILE* VfsOpen (FILE* file, string path) { if (!file) return NULL; // Parse string uint32 dev = VfsParsePath(&path); file->DeviceId = dev; // Device not found, or Open routine doesn't exist if (dev == BAD || !fsArray[mpArray[dev].FsId].Open) return NULL; // Ask the FS to do the 'opening' return fsArray[mpArray[dev].FsId].Open(&mpArray[dev],file,path); } DirectoryEntry* VfsTest (string path) { // Parse string uint32 dev = VfsParsePath(&path); // Device not found, or Open routine doesn't exist if (dev == BAD || !fsArray[mpArray[dev].FsId].Test) return NULL; // Ask the FS to do the 'opening' return fsArray[mpArray[dev].FsId].Test(&mpArray[dev],path); } FILE* VfsClose (FILE* file) { if (!file) return NULL; MountPoint* mp = &(mpArray[file->DeviceId]); if (!fsArray[mp->FsId].Close) return NULL; return fsArray[mp->FsId].Close(mp,file); } uint32 VfsRead (FILE* file, uint32 bsz, uint32 n, uint8* buffer) { if (!file) return NULL; MountPoint* mp = &(mpArray[file->DeviceId]); if (!fsArray[mp->FsId].Read) return NULL; return fsArray[mp->FsId].Read(mp, file, bsz, n, buffer); } uint32 VfsWrite (FILE* file, uint32 bsz, uint32 n, uint8* buffer) { if (!file) return NULL; MountPoint* mp = &(mpArray[file->DeviceId]); if (!fsArray[mp->FsId].Write) return NULL; return fsArray[mp->FsId].Write(mp, file, bsz, n, buffer); } DirectoryEntry* VfsReadDirectory (FILE* handle, uint32 index) { if (!handle) return NULL; MountPoint* mp = &(mpArray[handle->DeviceId]); if (!fsArray[mp->FsId].ReadDirectory) return NULL; return fsArray[mp->FsId].ReadDirectory(mp, handle, index); }