209 lines
4.8 KiB
C
209 lines
4.8 KiB
C
#include <memory.h>
|
|
#include <stdlib.h>
|
|
#include <fileio.h>
|
|
#include <debugio.h>
|
|
|
|
#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);
|
|
}
|