Kieron Morris 64b3c9a7ba Apache License
Added the apache license to all source files, accounting for authors. Also added a license.md containing the apache license + contributors.md listing all contributors.
2021-06-22 21:31:17 +01:00

781 lines
27 KiB
ObjectPascal

// Copyright 2021 Kieron Morris
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{
Driver->Storage->VFS - Virtual File System
@author(Kieron Morris kjm@kieronmorris.me)
}
unit vfs;
interface
uses
hashmap, strings, lmemorymanager, lists, tracer, console;
type
TOpenMode = (omReadOnly, omWriteOnly, omReadWrite);
TWriteMode = (wmRewrite, wmAppend, wmNew);
TError = (eNone, eUnknown, eFileInUse, eWriteOnly, eReadOnly, eFileDoesNotExist, eDirectoryDoesNotExist, eDirectoryAlreadyExists, eNotADirectory, eDiskFull, eFilenameTooLong, eDirectoryFull);
PError = ^TError;
TIsPathValid = (pvInvalid, pvFile, pvDirectory);
TRegError = (pvUnknown, pvNotRegistered, pvRegistered, pvUnregistered);
TFileHandle = uint32;
{ Callbacks }
TOpenFile = function(Handle : uint32; Filename : pchar; OpenMode : TOpenMode; WriteMode : TWriteMode; Lock : Boolean; Error : PError) : TFileHandle;
TWriteFile = function(Handle : uint32; FileHandle : TFileHandle; Position : uint32; Buffer : puint8; Length : uint32) : uint32;
TReadFile = function(Handle : uint32; FileHandle : TFileHandle; Position : uint32; Buffer : puint8; Length : uint32) : uint32;
TFileSize = function(Handle : uint32; Filename : pchar; error : puint8) : uint32;
TCloseFile = function(Handle : uint32; Filehandle : TFileHandle) : boolean;
TMakeDirectory = function(Handle : uint32; Path : pchar) : TError;
TGetDirectories = function(Handle : uint32; Path : pchar) : PHashMap;
TPathValid = function(Handle : uint32; Path : pchar) : TIsPathValid;
TObjectType = (otVDIRECTORY, otDRIVE, otDEVICE, otVFILE, otMOUNT, otDIRECTORY, otFILE);
TVFSDrive = record
DriveHandle : uint32;
MakeDirectory : TMakeDirectory;
GetDirectories : TGetDirectories;
OpenFile : TOpenFile;
CloseFile : TCloseFile;
ReadFile : TReadFile;
WriteFile : TWriteFile;
FileSize : TFileSize;
PathValid : TPathValid;
end;
PVFSDrive = ^TVFSDrive;
TVFSDevice = record
DeviceHandle : uint32;
MakeDirectory : TMakeDirectory;
GetDirectories : TGetDirectories;
OpenFile : TOpenFile;
CloseFile : TCloseFile;
ReadFile : TReadFile;
WriteFile : TWriteFile;
FileSize : TFileSize;
PathValid : TPathValid;
end;
PVFSDevice = ^TVFSDevice;
TVFSFile = record
ReadFile : TReadFile;
WriteFile : TWriteFile;
end;
PVFSFile = ^TVFSFile;
TVFSMount = record
Path : pchar;
ObjectType : TObjectType;
Reference : void;
end;
PVFSMount = ^TVFSMount;
PVFSObject = ^TVFSObject;
TVFSObject = record
Parent : PVFSObject;
ObjectName : pchar;
ObjectType : TObjectType;
Reference : void;
end;
var
Root : PVFSObject;
CurrentDirectory : pchar = nil;
PushPopDirectory : PLinkedListBase;
procedure init();
Function OpenFile(Filename : pchar; OpenMode : TOpenMode; WriteMode : TWriteMode; Lock : Boolean; Error : PError) : TFileHandle;
function WriteFile(FileHandle : TFileHandle; Position : uint32; Buffer : puint8; Length : uint32) : uint32;
function ReadFile(FileHandle : TFileHandle; Position : uint32; Buffer : puint8; Length : uint32) : uint32;
function CloseFile(Filehandle : TFileHandle) : boolean;
function FileSize(Filename : pchar; error : puint8) : uint32;
function CreateDirectory(Handle : uint32; Path : pchar) : TError;
function GetDirectories(Handle : uint32; Path : pchar) : PHashMap;
function PathValid(Path : pchar) : TIsPathValid;
function changeDirectory(Path : pchar) : TIsPathValid;
function getWorkingDirectory : pchar;
//VFS Functions
function newVirtualDirectory(Path : pchar) : TError;
//Driver Functions
function registerDrive(DriveHandle : uint32; DriveName : PChar; CBMakeDirectory : TMakeDirectory; CBGetDirectories : TGetDirectories; CBOpenFile : TOpenFile; CBCloseFile : TCloseFile; CBReadFile : TReadFile; CBWriteFile : TWriteFile; CBFileSize : TFileSize; CBPathValid : TPathValid) : TRegError;
function registerDevice(DeviceHandle : uint32; DeviceName : PChar; CBMakeDirectory : TMakeDirectory; CBGetDirectories : TGetDirectories; CBOpenFile : TOpenFile; CBCloseFile : TCloseFile; CBReadFile : TReadFile; CBWriteFile : TWriteFile; CBFileSize : TFileSize; CBPathValid : TPathValid) : TRegError;
implementation
uses
terminal;
{ Internal Functions }
function makeRelative(Path : pchar; From : pchar) : pchar;
var
Result : pchar;
Tmp : pchar;
begin
tracer.push_trace('vfs.makeRelative.enter');
Result:= nil;
if StringEquals(Path, From) then begin
Result:= stringCopy('/');
end else begin
if StringContains(Path, From) then begin
if (Path[0] = From[0]) and (Path[StringSize(From)-1] = From[StringSize(From)-1]) then begin
Tmp:= Path;
inc(tmp, StringSize(From));
Result:= stringCopy(tmp);
end;
end;
end;
makeRelative:= Result;
tracer.push_trace('vfs.makeRelative.exit');
end;
function createDummyObject(ObjType : TObjectType) : PVFSObject;
begin
tracer.push_trace('vfs.createDummyObject.enter');
createDummyObject:= PVFSObject(kalloc(sizeof(TVFSObject)));
createDummyObject^.ObjectType:= ObjType;
tracer.push_trace('vfs.createDummyObject.exit');
end;
function createVirtualDirectory : PVFSObject;
begin
tracer.push_trace('vfs.createVirtualDirectory.enter');
createVirtualDirectory:= PVFSObject(kalloc(sizeof(TVFSObject)));
createVirtualDirectory^.ObjectType:= otVDIRECTORY;
createVirtualDirectory^.Reference:= void(hashmap.new());
tracer.push_trace('vfs.createVirtualDirectory.exit');
end;
function CombineToAbsolutePath(List : PLinkedListBase; Count : uint32) : pchar;
var
new, old : pchar;
i : uint32;
begin
tracer.push_trace('vfs.CombineToAbsolutePath.enter');
CombineToAbsolutePath:= nil;
if STRLL_Size(List) < (Count-1) then begin
tracer.push_trace('vfs.CombineToAbsolutePath.shortexit');
exit;
end;
new:= stringCopy('/');
If Count > 0 then begin
for i:=0 to Count-1 do begin
if i = 0 then begin
old:= StringConcat(new, STRLL_Get(List, i));
end else begin
old:= StringConcat(new, '/');
kfree(void(new));
new:= old;
old:= StringConcat(new, STRLL_Get(List, i));
end;
kfree(void(new));
new:= old;
end;
end;
CombineToAbsolutePath:= new;
tracer.push_trace('vfs.CombineToAbsolutePath.exit');
end;
function evaluatePath(Path : pchar) : pchar;
var
List : PLinkedListBase;
i : uint32;
elm : pchar;
begin
tracer.push_trace('vfs.evaluatePath.enter');
List:= STRLL_FromString(Path, '/');
if STRLL_Size(List) > 0 then begin
for i:=STRLL_Size(List)-1 downto 0 do begin
elm:= STRLL_Get(List, i);
if elm <> nil then begin
if StringEquals(elm,'..') then begin
STRLL_Delete(List, i);
if (i > 0) then STRLL_Delete(List, i-1);
end;
if StringEquals(elm,'.') then begin
STRLL_Delete(List, i);
end;
end;
end;
end;
evaluatePath:= CombineToAbsolutePath(List, STRLL_Size(List));
STRLL_Free(List);
tracer.push_trace('vfs.evaluatePath.exit');
end;
function getAbsolutePath(Obj : PVFSObject) : pchar;
var
buf, new, delim : pchar;
iter : PVFSObject;
begin
tracer.push_trace('vfs.getAbsolutePath.enter');
delim:= stringCopy('/');
buf:= nil;
iter:= Obj;
if iter <> nil then begin
if iter^.Parent = nil then buf:= stringCopy(iter^.ObjectName);
while iter^.Parent <> nil do begin
new:= StringConcat('/', iter^.ObjectName);
if buf = nil then
buf:= stringCopy(new)
else
buf:= StringConcat(new, buf);
kfree(void(new));
iter:= iter^.Parent;
end;
end;
kfree(void(delim));
getAbsolutePath:= buf;
tracer.push_trace('vfs.getAbsolutePath.exit');
end;
function MakeAbsolutePath(Path : PChar) : pchar;
var
AbsPath : pchar;
TempPath : pchar;
begin
tracer.push_trace('vfs.MakeAbsolutePath.enter');
if Path[0] = '/' then AbsPath:= stringCopy(Path) else begin
if CurrentDirectory[StringSize(CurrentDirectory)-1] <> '/' then
TempPath:= StringConcat(CurrentDirectory, '/')
else
TempPath:= stringCopy(CurrentDirectory);
AbsPath:= StringConcat(TempPath, Path);
kfree(void(TempPath));
end;
MakeAbsolutePath:= AbsPath;
tracer.push_trace('vfs.MakeAbsolutePath.exit');
end;
function GetObjectFromPath(path : pchar) : PVFSObject;
var
Obj : PVFSObject;
NewObj : PVFSObject;
SplitPath : PLinkedListBase;
ht : PHashMap;
i : uint32;
item : pchar;
begin
tracer.push_trace('vfs.GetObjectFromPath.enter');
SplitPath:= STRLL_FromString(path, '/');
Obj:= Root;
if STRLL_Size(SplitPath) > 0 then begin
for i:=0 to STRLL_Size(SplitPath)-1 do begin
ht:= PHashMap(Obj^.Reference);
item:= STRLL_Get(SplitPath, i);
NewObj:= PVFSObject(hashmap.get(ht, item));
if NewObj = nil then begin
GetObjectFromPath:= nil;
tracer.push_trace('vfs.GetObjectFromPath.shortexit_1');
exit;
end;
Case NewObj^.ObjectType of
otVDIRECTORY,otMOUNT:begin
Obj:= NewObj;
end;
else begin
Obj:= NewObj;
tracer.push_trace('vfs.GetObjectFromPath.shortexit_2');
Break;
end;
end;
end;
end;
GetObjectFromPath:= Obj;
tracer.push_trace('vfs.GetObjectFromPath.exit');
end;
Procedure ChangeCurrentDirectoryValue(new : pchar);
begin
tracer.push_trace('vfs.ChangeCurrentDirectoryValue.enter');
if CurrentDirectory <> nil then kfree(void(CurrentDirectory));
CurrentDirectory:= nil;
CurrentDirectory:= stringCopy(new);
tracer.push_trace('vfs.ChangeCurrentDirectoryValue.exit');
end;
Function GetDirectoryListing(Path : pchar) : PHashMap;
var
Obj : PVFSObject;
ObjPath : pchar;
RelPath : pchar;
begin
tracer.push_trace('vfs.GetDirectoryListing.enter');
Obj:= GetObjectFromPath(Path);
if Obj <> nil then begin
Case Obj^.ObjectType of
otVDIRECTORY:begin
GetDirectoryListing:= PHashMap(Obj^.Reference);
end;
otDRIVE:begin
ObjPath:= getAbsolutePath(Obj);
RelPath:= makeRelative(Path, ObjPath);
GetDirectoryListing:= PVFSDrive(Obj^.Reference)^.GetDirectories(PVFSDrive(Obj^.Reference)^.DriveHandle, RelPath); //Fix this to be relative path!!!
kfree(void(ObjPath));
kfree(void(RelPath));
end;
otDEVICE:begin
ObjPath:= getAbsolutePath(Obj);
RelPath:= makeRelative(Path, ObjPath);
GetDirectoryListing:= PVFSDevice(Obj^.Reference)^.GetDirectories(PVFSDevice(Obj^.Reference)^.DeviceHandle, RelPath); //Fix this to be the relative path
kfree(void(ObjPath));
kfree(void(RelPath));
end;
otFILE, otDIRECTORY, otVFILE:begin
GetDirectoryListing:= nil;
end;
otMOUNT:begin
GetDirectoryListing:= GetDirectoryListing(PVFSMount(Obj^.Reference)^.Path);
end;
end;
end else begin
GetDirectoryListing:= nil;
end;
tracer.push_trace('vfs.GetDirectoryListing.exit');
end;
{ Driver Functions }
function registerDrive(DriveHandle : uint32; DriveName : PChar; CBMakeDirectory : TMakeDirectory; CBGetDirectories : TGetDirectories; CBOpenFile : TOpenFile; CBCloseFile : TCloseFile; CBReadFile : TReadFile; CBWriteFile : TWriteFile; CBFileSize : TFileSize; CBPathValid : TPathValid) : TRegError;
var
Drive : PVFSObject;
ht : PHashMap;
NewObj : PVFSObject;
NewDrive : PVFSDrive;
begin
Drive:= GetObjectFromPath('/disk');
ht:= PHashMap(Drive^.Reference);
NewObj:= PVFSObject(kalloc(sizeof(TVFSObject)));
NewObj^.Parent:= Drive;
NewObj^.ObjectName:= stringCopy(DriveName);
NewObj^.ObjectType:= otDRIVE;
NewDrive:= PVFSDrive(kalloc(sizeof(TVFSDrive)));
NewDrive^.DriveHandle:= DriveHandle;
NewDrive^.MakeDirectory:= CBMakeDirectory;
NewDrive^.GetDirectories:= CBGetDirectories;
NewDrive^.OpenFile:= CBOpenFile;
NewDrive^.CloseFile:= CBCloseFile;
NewDrive^.ReadFile:= CBReadFile;
NewDrive^.WriteFile:= CBWriteFile;
NewDrive^.FileSize:= CBFileSize;
NewDrive^.PathValid:= CBPathValid;
NewObj^.Reference:= void(NewDrive);
hashmap.add(ht, stringCopy(DriveName), void(NewObj));
end;
function registerDevice(DeviceHandle : uint32; DeviceName : PChar; CBMakeDirectory : TMakeDirectory; CBGetDirectories : TGetDirectories; CBOpenFile : TOpenFile; CBCloseFile : TCloseFile; CBReadFile : TReadFile; CBWriteFile : TWriteFile; CBFileSize : TFileSize; CBPathValid : TPathValid) : TRegError;
var
Dev : PVFSObject;
ht : PHashMap;
NewObj : PVFSObject;
NewDev : PVFSDevice;
begin
Dev:= GetObjectFromPath('/dev');
ht:= PHashMap(Dev^.Reference);
NewObj:= PVFSObject(kalloc(sizeof(TVFSObject)));
NewObj^.Parent:= Dev;
NewObj^.ObjectName:= stringCopy(DeviceName);
NewObj^.ObjectType:= otDEVICE;
NewDev:= PVFSDevice(kalloc(sizeof(TVFSDevice)));
NewDev^.DeviceHandle:= DeviceHandle;
NewDev^.MakeDirectory:= CBMakeDirectory;
NewDev^.GetDirectories:= CBGetDirectories;
NewDev^.OpenFile:= CBOpenFile;
NewDev^.CloseFile:= CBCloseFile;
NewDev^.ReadFile:= CBReadFile;
NewDev^.WriteFile:= CBWriteFile;
NewDev^.FileSize:= CBFileSize;
NewDev^.PathValid:= CBPathValid;
NewObj^.Reference:= void(NewDev);
hashmap.add(ht, stringCopy(DeviceName), void(NewDev));
end;
{ Filesystem Functions }
Function OpenFile(Filename : pchar; OpenMode : TOpenMode; WriteMode : TWriteMode; Lock : Boolean; Error : PError) : TFileHandle;
begin
end;
function WriteFile(FileHandle : TFileHandle; Position : uint32; Buffer : puint8; Length : uint32) : uint32;
begin
end;
function ReadFile(FileHandle : TFileHandle; Position : uint32; Buffer : puint8; Length : uint32) : uint32;
begin
end;
function CloseFile(Filehandle : TFileHandle) : boolean;
begin
end;
function FileSize(Filename : pchar; error : puint8) : uint32;
begin
end;
function CreateDirectory(Handle : uint32; Path : pchar) : TError;
begin
end;
function GetDirectories(Handle : uint32; Path : pchar) : PHashMap;
begin
end;
function PathValid(Path : pchar) : TIsPathValid;
var
Obj : PVFSObject;
ObjPath : pchar;
RelPath : pchar;
AbsPath : pchar;
CopyPath : pchar;
MntPath : pchar;
ValidCallback : TPathValid;
begin
tracer.push_trace('vfs.PathValid.enter');
PathValid:= pvInvalid;
Obj:= GetObjectFromPath(Path);
if Obj <> nil then begin
Case Obj^.ObjectType of
otVDIRECTORY:begin
PathValid:= pvDirectory;
end;
otDRIVE:begin
ObjPath:= getAbsolutePath(Obj);
RelPath:= makeRelative(Path, ObjPath);
ValidCallback:= PVFSDrive(Obj^.Reference)^.PathValid;
if ValidCallback <> nil then
PathValid:= ValidCallback(PVFSDrive(Obj^.Reference)^.DriveHandle, RelPath)
else
PathValid:= pvInvalid;
kfree(void(ObjPath));
kfree(void(RelPath));
end;
otDEVICE:begin
ObjPath:= getAbsolutePath(Obj);
RelPath:= makeRelative(Path, ObjPath);
ValidCallback:= PVFSDevice(Obj^.Reference)^.PathValid;
if ValidCallback <> nil then
PathValid:= ValidCallback(PVFSDevice(Obj^.Reference)^.DeviceHandle, RelPath)
else
PathValid:= pvInvalid;
kfree(void(ObjPath));
kfree(void(RelPath));
end;
otFILE, otVFILE:begin
PathValid:= pvFile;
end;
otMOUNT:begin
{ Get the absolute path of this object, i.e. /mnt/mount1 }
ObjPath:= getAbsolutePath(Obj);
{ Make our path relative, i.e. /mnt/mount1/myfile becomes /myfile }
RelPath:= makeRelative(Path, ObjPath);
{ Grab the Redirect Path i.e. /disk/disk1 }
MntPath:= PVFSMount(Obj^.Reference)^.Path;
{ Ensure that if there isn't a '/' between the RelPath & MntPath we add one }
If (MntPath[StringSize(MntPath)-1] <> '/') AND (RelPath[0] <> '/') then
CopyPath:= StringConcat(MntPath, '/')
else
CopyPath:= StringCopy(MntPath);
{ Concat MntPath + RelPath, i.e. above examples would become /disk/disk1/myfile }
AbsPath:= StringConcat(MntPath, RelPath);
{ Recursively call PathValid on our new path }
PathValid:= PathValid(AbsPath);
{ Free everything we allocated }
kfree(void(AbsPath));
kfree(void(RelPath));
kfree(void(CopyPath));
kfree(void(ObjPath));
end;
end;
end;
tracer.push_trace('vfs.PathValid.exit');
end;
function changeDirectory(Path : pchar) : TIsPathValid;
var
TempPath : pchar;
AbsPath : pchar;
Validity : TIsPathValid;
begin
tracer.push_trace('vfs.changeDirectory.enter');
TempPath:= MakeAbsolutePath(Path);
AbsPath:= evaluatePath(TempPath);
kfree(void(TempPath));
Validity:= PathValid(AbsPath);
if (Validity = pvDirectory) then begin
ChangeCurrentDirectoryValue(AbsPath);
end;
changeDirectory:= Validity;
kfree(void(AbsPath));
tracer.push_trace('vfs.changeDirectory.exit');
end;
{ VFS Functions }
function newVirtualDirectory(Path : pchar) : TError;
var
TempPath : pchar;
AbsPath : pchar;
SplitPath : PLinkedListBase;
SplitParentPath : PLinkedListBase;
ParentDirectoryPath : pchar;
ObjectName : pchar;
Obj : PVFSObject;
Map : PHashMap;
Entry : PVFSObject;
Key : pchar;
begin
tracer.push_trace('vfs.newVirtualDirectory.enter');
newVirtualDirectory:= eUnknown;
AbsPath:= MakeAbsolutePath(Path);
SplitPath:= STRLL_FromString(AbsPath, '/');
ObjectName:= STRLL_Get(SplitPath, STRLL_Size(SplitPath)-1);
ParentDirectoryPath:= CombineToAbsolutePath(SplitPath, STRLL_Size(SplitPath)-1);
SplitParentPath:= STRLL_FromString(ParentDirectoryPath, '/');
Obj:= GetObjectFromPath(ParentDirectoryPath);
if Obj = nil then begin
newVirtualDirectory:= eDirectoryDoesNotExist;
end else begin
Case Obj^.ObjectType of
otDRIVE, otDEVICE, otVFILE:begin
newVirtualDirectory:= eNotADirectory;
tracer.push_trace('vfs.newVirtualDirectory.shortexit');
exit;
end;
end;
Map:= PHashMap(Obj^.Reference);
Key:= STRLL_Get(SplitPath, STRLL_Size(SplitPath)-1);
Entry:= PVFSObject(hashmap.get(Map, Key));
If Entry = nil then begin
Entry:= createVirtualDirectory();
Entry^.ObjectName:= stringCopy(ObjectName);
Entry^.Parent:= Obj;
hashmap.add(Map, Key, void(Entry));
end else begin
newVirtualDirectory:= eDirectoryAlreadyExists;
end;
end;
tracer.push_trace('vfs.newVirtualDirectory.exit');
end;
function getWorkingDirectory : pchar;
begin
tracer.push_trace('vfs.getWorkingDirectory.enter');
getWorkingDirectory:= CurrentDirectory;
tracer.push_trace('vfs.getWorkingDirectory.exit');
end;
{ Terminal Commands }
procedure VFS_COMMAND_PUSHD(params : PParamList);
var
Output : pchar;
WD : pchar;
begin
WD:= StringCopy(CurrentDirectory);
STRLL_Add(PushPopDirectory, WD);
Output:= StringConcat(WD, ' saved to stack.');
WritestringlnWND(Output, getTerminalHWND);
kfree(void(Output));
end;
procedure VFS_COMMAND_POPD(params : PParamList);
var
Output : pchar;
WD : pchar;
begin
if STRLL_Size(PushPopDirectory) > 0 then begin
WD:= STRLL_Get(PushPopDirectory, STRLL_Size(PushPopDirectory)-1);
if changeDirectory(WD) = pvDirectory then begin
Output:= StringConcat(WD, ' popped from the stack.');
WritestringlnWND(Output, getTerminalHWND);
kfree(void(Output));
end else begin
Output:= StringConcat(WD, ' popped, but was invalid!');
WritestringlnWND(Output, getTerminalHWND);
kfree(void(Output));
end;
STRLL_Delete(PushPopDirectory, STRLL_Size(PushPopDirectory)-1);
end else begin
WritestringlnWND('No working directory in the stack!', getTerminalHWND);
end;
end;
procedure VFS_COMMAND_LS(params : PParamList);
var
Map : PHashMap;
Item : PHashItem;
obj : PVFSObject;
i : uint32;
col : uint32;
begin
tracer.push_trace('vfs.VFS_COMMAND_LS.enter');
Map:= GetDirectoryListing(CurrentDirectory);
if Map <> nil then begin
for i:=0 to Map^.Size-1 do begin
Item:= Map^.Table[i];
while Item <> nil do begin
obj:= PVFSObject(Item^.Data);
console.writestringWND(' ', getTerminalHWND);
col:= console.combinecolors($FFFF, $0000);
case obj^.ObjectType of
otVDIRECTORY : col:= console.combinecolors($1587, $0000);
otDRIVE : col:= console.combinecolors($F000, $0000);
otDEVICE : col:= console.combinecolors($FFFF, $F000);
otVFILE : col:= console.combinecolors($FFFF, $C018);
otMOUNT : col:= console.combinecolors($0000, $2638);
otFILE : col:= console.combinecolors($FFFF, $0000);
otDIRECTORY : col:= console.combinecolors($547F, $0000);
end;
WritestringlnExWND(Item^.Key, col, getTerminalHWND);
Item:= Item^.Next;
end;
end;
end else begin
writestringlnWND('An internal error occured!', getTerminalHWND);
end;
tracer.push_trace('vfs.VFS_COMMAND_LS.exit');
end;
procedure VFS_COMMAND_CD(params : PParamList);
var
Path : pchar;
Temp1, Temp2 : pchar;
Result : TIsPathValid;
i : uint32;
begin
tracer.push_trace('vfs.VFS_COMMAND_CD.enter');
if ParamCount(Params) > 0 then begin
for i:=0 to ParamCount(Params)-1 do begin
if i = 0 then begin
Temp1:= StringCopy(GetParam(i, params));
Path:= StringCopy(Temp1);
kfree(void(Temp1));
end else begin
Temp1:= StringConcat(' ', GetParam(i, Params));
Temp2:= StringConcat(Path, Temp1);
kfree(void(Temp1));
kfree(void(Path));
Path:= Temp2;
end;
end;
Result:= changeDirectory(Path);
case Result of
pvInvalid:begin
writestringWND('"', getTerminalHWND);
writestringWND(Path, getTerminalHWND);
writestringlnWND('" is not a valid path.', getTerminalHWND);
end;
pvFile:begin
writestringWND('"', getTerminalHWND);
writestringWND(Path, getTerminalHWND);
writestringlnWND('" is not a directory.', getTerminalHWND);
end;
end;
kfree(void(Path));
end;
tracer.push_trace('vfs.VFS_COMMAND_CD.exit');
end;
{ Init }
procedure init();
var
ht : PHashMap;
obj : PVFSObject;
rel : pchar;
begin
tracer.push_trace('vfs.init.enter');
{ VFS Root Creation }
Root:= createVirtualDirectory();
Root^.Parent:= nil;
Root^.ObjectName:= stringCopy('/');
{ Init Push/Pop Stack for PUSHD & POPD }
PushPopDirectory:= STRLL_New;
{ Move to root of VFS }
ChangeCurrentDirectoryValue('/');
{ Create the Default VFS Directories }
newVirtualDirectory('/dev');
newVirtualDirectory('/disk');
newVirtualDirectory('/cfg');
// rel:= makeRelative('/disk/SDA/mydirectory/myfile', '/disk/SDA');
// if rel <> nil then outputln('VFS', rel) else outputln('VFS', 'REL IS NULL!');
//outputln('VFS', makeRelative('/test/mydisk/mything', '/test/mydisk'));
//while true do begin end;
{ Register Terminal Commands }
terminal.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
terminal.registerCommand('CD', @VFS_COMMAND_CD, 'Set working directory.');
terminal.registerCommand('PUSHD', @VFS_COMMAND_PUSHD, 'Push the working directory.');
terminal.registerCommand('POPD', @VFS_COMMAND_POPD, 'Pop the working directory.');
//ht:= PHashMap(Root^.Reference);
//hashmap.add(ht, 'VDirectory', void(newDummyObject(otVDIRECTORY)));
//hashmap.add(ht, 'Drive', void(newDummyObject(otDRIVE)));
//hashmap.add(ht, 'Device', void(newDummyObject(otDEVICE)));
//hashmap.add(ht, 'virtualFile', void(createDummyObject(otVFILE)));
//hashmap.add(ht, 'Mount', void(newDummyObject(otMOUNT)));
//hashmap.add(ht, 'Directory', void(newDummyObject(otDIRECTORY)));
//hashmap.add(ht, 'File', void(newDummyObject(otFILE)));}
//otVDIRECTORY, otDRIVE, otDEVICE, otVFILE, otMOUNT, otDIRECTORY, otFILE)
//registerDrive(1337, 'TestDrive', nil, nil, nil, nil, nil, nil, nil, @fake_drive_path_valid);
tracer.push_trace('vfs.init.exit');
end;
end.