Tiberiu Chibici
e3b3584734
==================================================== Mainly changed: Tasking + Implemented multitasking
244 lines
5.5 KiB
C
244 lines
5.5 KiB
C
#include <array.h>
|
|
#include <memory.h>
|
|
#include <fileio.h>
|
|
#include <debugio.h>
|
|
#include <stdlib.h>
|
|
|
|
#define BAD 0xffffffff
|
|
|
|
DynamicArray fsList;
|
|
DynamicArray mpList;
|
|
|
|
FileSystem* fsArray;
|
|
MountPoint* mpArray;
|
|
|
|
void VfsInstall ()
|
|
{
|
|
DynamicArrayCreate(sizeof(FileSystem), &fsList);
|
|
DynamicArrayCreate(sizeof(MountPoint), &mpList);
|
|
|
|
fsArray = (FileSystem*) fsList.Data;
|
|
mpArray = (MountPoint*) mpList.Data;
|
|
|
|
Log("VFS", "%#Vfs now in business.\n", ColorLightGreen);
|
|
}
|
|
|
|
void VfsInstallFs (FileSystem* fs)
|
|
{
|
|
fs->Id = fsList.Size;
|
|
DynamicArrayPush(fs, &fsList);
|
|
|
|
Log("VFS", "Installed file system %#%s%# (id=%u).\n", ColorWhite, fs->Name,
|
|
ColorLightGray, fs->Id);
|
|
}
|
|
|
|
int32 _VfsFindDevice (string name)
|
|
{
|
|
int32 i;
|
|
for (i = 0; (uint32)i < mpList.Size; i++)
|
|
if (mpArray[i].Id != BAD && strcmp (name, mpArray[i].Name) == 0) return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
string _VfsGetDevice (string path, int32* dev)
|
|
{
|
|
// Make sure path is valid
|
|
if (!path || *path != '/') {
|
|
*dev = -1; return NULL;
|
|
}
|
|
|
|
// Do we need to return root?
|
|
path++;
|
|
if (*path == '\0') return NULL; // Yes, but not implemented yet
|
|
|
|
// Find the next '/'
|
|
int32 i, index = -1, len = strlen(path);
|
|
for (i = 0; i < len && index == -1; i++)
|
|
if (path[i] == '/') index = i;
|
|
|
|
if (index == -1) index = len;
|
|
|
|
// Find the device
|
|
*dev = -1;
|
|
for (i = 0; (uint32)i < mpList.Size && *dev == -1; i++)
|
|
if (mpArray[i].Id != BAD && strncmp(path, mpArray[i].Name, index) == 0)
|
|
*dev = i;
|
|
|
|
return &path[index];
|
|
}
|
|
|
|
int32 _VfsDetectFs (MountPoint* mp)
|
|
{
|
|
int32 i;
|
|
for (i = 0; (uint32)i < fsList.Size; i++)
|
|
if (fsArray[i].Detect && fsArray[i].Detect(mp)) return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int32 VfsTestDevname (string name)
|
|
{
|
|
// Check if name exists
|
|
uint8 success = (_VfsFindDevice(name) == -1);
|
|
|
|
// Set up for search
|
|
char find;
|
|
uint32 len = strlen(name);
|
|
name[len+1] = '\0';
|
|
|
|
// Name exists? Try a number
|
|
for (find = '0'; find <= '9' && !success; find++)
|
|
{
|
|
name[len] = find;
|
|
success = (_VfsFindDevice(name) == -1);
|
|
}
|
|
|
|
// Whoa... nothing? Try the alphabet.
|
|
for (find = 'a'; find <= 'z' && !success; find++)
|
|
{
|
|
name[len] = find;
|
|
success = (_VfsFindDevice(name) == -1);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
MountPoint* VfsMount (string devname, DevReadRoutine R, DevWriteRoutine W, uint32 bs)
|
|
{
|
|
// Create a mount point
|
|
MountPoint mp ;
|
|
strcpy(mp.Name, devname);
|
|
mp.BlockSize = bs;
|
|
mp.Read = R;
|
|
mp.Write = W;
|
|
|
|
// Detect file system
|
|
int32 fsid = _VfsDetectFs(&mp);
|
|
if (fsid == -1) {
|
|
Error("VFS", "%#Failed to mount device %s: could not find a file system.\n", ColorLightRed, devname);
|
|
return NULL;
|
|
}
|
|
mp.FsId = (uint32) fsid;
|
|
|
|
// Rename if it has problems
|
|
if (!VfsTestDevname(mp.Name)) {
|
|
Error("VFS", "%#Failed to mount device %s: bad name.\n", ColorLightRed, devname);
|
|
return NULL;
|
|
}
|
|
|
|
// Find an empty slot
|
|
uint32 empty = BAD, i;
|
|
for (i = 0; i < mpList.Size && empty == BAD; i++)
|
|
if (mpArray[i].Id == BAD) empty = i;
|
|
|
|
// Mount it
|
|
if (empty == BAD) {
|
|
mp.Id = mpList.Size;
|
|
DynamicArrayPush(&mp, &mpList);
|
|
}
|
|
|
|
else {
|
|
mp.Id = empty;
|
|
memcpy ( &mpArray[empty], &mp, sizeof(MountPoint));
|
|
}
|
|
|
|
// Tell the FS to mount the device
|
|
if (fsArray[fsid].MountDevice)
|
|
fsArray[fsid].MountDevice(&mpArray[mp.Id]);
|
|
|
|
// Log
|
|
Log("VFS", "Mounted device %#%s%# using the %#%s%# file system.\n", ColorWhite, mp.Name,
|
|
ColorLightGray, ColorWhite, fsArray[fsid].Name, ColorLightGray);
|
|
|
|
return &mpArray[mp.Id];
|
|
}
|
|
|
|
void VfsUnmount (uint32 devid)
|
|
{
|
|
if (fsArray[mpArray[devid].FsId].UnmountDevice)
|
|
fsArray[mpArray[devid].FsId].UnmountDevice(&mpArray[devid],0);
|
|
|
|
// Invalidate ID
|
|
mpArray[devid].Id = BAD;
|
|
|
|
// We shouldn't remove it from the array, because it will invalidate
|
|
// all other devices' IDs.
|
|
}
|
|
|
|
// Returns pointer to FILE structure that was inputed if success, null otherwise
|
|
FILE* VfsOpen (FILE* file, string path)
|
|
{
|
|
if (!file) return NULL;
|
|
|
|
// Parse string
|
|
int32 dev; string temp;
|
|
temp = _VfsGetDevice(path, &dev);
|
|
file->DeviceId = dev;
|
|
|
|
// Device not found, or Open routine doesn't exist
|
|
if (dev == -1 || !fsArray[mpArray[dev].FsId].Open) return NULL;
|
|
|
|
// Ask the FS to do the 'opening'
|
|
return fsArray[mpArray[dev].FsId].Open(&mpArray[dev],file,temp);
|
|
}
|
|
|
|
DirectoryEntry* VfsTest (string path)
|
|
{
|
|
// Parse string
|
|
int32 dev;
|
|
path = _VfsGetDevice(path, &dev);
|
|
|
|
// Device not found, or Open routine doesn't exist
|
|
if (dev == -1 || !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]);
|
|
|
|
// Don't try to read files as directories
|
|
if ((handle->Flags & 0x7) == FileFile) return NULL;
|
|
|
|
// Ask FS to make the read
|
|
if (!fsArray[mp->FsId].ReadDirectory) return NULL;
|
|
return fsArray[mp->FsId].ReadDirectory(mp, handle, index);
|
|
}
|
|
|
|
MountPoint* VfsGetMountPoint (uint32 dev_id)
|
|
{
|
|
if (dev_id < mpList.Size) return &mpArray[dev_id];
|
|
return NULL;
|
|
}
|