luxos/Kernel/hal/vfs.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);
}