215 lines
5.1 KiB
C
215 lines
5.1 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;
|
|
|
|
void VfsInstall ()
|
|
{
|
|
fsArray = (FileSystem*) kmalloc(MAX_FS_COUNT * sizeof(FileSystem));
|
|
fsCount = 0;
|
|
|
|
mpArray = (MountPoint*) kmalloc(32 * sizeof(MountPoint));
|
|
mpCount = 0;
|
|
mpAllocated = 32;
|
|
|
|
Log("VFS", "%#VFS now in business.\n", ColorLightGreen);
|
|
}
|
|
|
|
uint8 VfsInstallFs (FileSystem* fs)
|
|
{
|
|
if (fsCount >= MAX_FS_COUNT) {
|
|
Error("VFS", "%#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;
|
|
Log("VFS", "Installed file system %#%s.\n", ColorWhite, fs->Name);
|
|
return 1;
|
|
}
|
|
|
|
uint32 VfsFindDevice (string dev)
|
|
{
|
|
uint32 i;
|
|
for (i = 0; i < mpCount; i++)
|
|
if (mpArray[i].Id != BAD && 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[i].Detect && fsArray[i].Detect(R, BlockSize))
|
|
fsId = i;
|
|
|
|
if (fsId == BAD) {
|
|
Error("VFS", "%#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[mpIndex].Name, Name, sizeof(char) * MAX_MOUNTPOINTNAME_LEN);
|
|
|
|
// Tell file system to mount the device
|
|
if (fsArray[mpArray[mpIndex].FsId].MountDevice)
|
|
fsArray[mpArray[mpIndex].FsId].MountDevice(&mpArray[mpIndex]);
|
|
|
|
Log("VFS", "Mounted device %#%s%# using the %#%s%# file system.\n", ColorWhite, Name,
|
|
ColorLightGray, ColorWhite, fsArray[fsId].Name, ColorLightGray);
|
|
return 1;
|
|
}
|
|
|
|
void VfsUnmount (uint32 dev_id)
|
|
{
|
|
if (fsArray[mpArray[dev_id].FsId].UnmountDevice)
|
|
fsArray[mpArray[dev_id].FsId].UnmountDevice(&mpArray[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);
|
|
}
|