Added relative/absolute path functions to vfs.pas

Implemented stringContains in strings.pas

git-svn-id: https://spexeah.com:8443/svn/Asuro@1432 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c
This commit is contained in:
kieron 2020-07-20 22:34:28 +00:00
parent 2b73fa4f44
commit d642eafe24
2 changed files with 357 additions and 15 deletions

View File

@ -3,12 +3,12 @@ unit vfs;
interface interface
uses uses
hashmap, strings, lmemorymanager; hashmap, strings, lmemorymanager, lists, tracer, console;
type type
TOpenMode = (omReadOnly, omWriteOnly, omReadWrite); TOpenMode = (omReadOnly, omWriteOnly, omReadWrite);
TWriteMode = (wmRewrite, wmAppend, wmNew); TWriteMode = (wmRewrite, wmAppend, wmNew);
TError = (eNone, eUnknown, eFileInUse, eWriteOnly, eReadOnly, eFileDoesNotExist, eDirectoryDoesNotExist, eDirectoryAlreadyExists); TError = (eNone, eUnknown, eFileInUse, eWriteOnly, eReadOnly, eFileDoesNotExist, eDirectoryDoesNotExist, eDirectoryAlreadyExists, eNotADirectory);
PError = ^TError; PError = ^TError;
TIsPathValid = (pvInvalid, pvFile, pvDirectory); TIsPathValid = (pvInvalid, pvFile, pvDirectory);
@ -24,10 +24,7 @@ type
TGetDirectories = function(Handle : uint32; Path : pchar) : PHashMap; TGetDirectories = function(Handle : uint32; Path : pchar) : PHashMap;
TPathValid = function(Handle : uint32; Path : pchar) : TIsPathValid; TPathValid = function(Handle : uint32; Path : pchar) : TIsPathValid;
TObjectType = (otVDIRECTORY, otDIRECTORY, otDEVICE, otFILE, otMOUNT); TObjectType = (otVDIRECTORY, otDRIVE, otDEVICE, otVFILE, otMOUNT, otDIRECTORY, otFILE);
TVFSVDirectory = record
Contents : PHashMap;
end;
TVFSDrive = record TVFSDrive = record
DriveHandle : uint32; DriveHandle : uint32;
MakeDirectory : TMakeDirectory; MakeDirectory : TMakeDirectory;
@ -39,6 +36,7 @@ type
FileSize : TFileSize; FileSize : TFileSize;
PathValid : TPathValid; PathValid : TPathValid;
end; end;
PVFSDrive = ^TVFSDrive;
TVFSDevice = record TVFSDevice = record
DeviceHandle : uint32; DeviceHandle : uint32;
MakeDirectory : TMakeDirectory; MakeDirectory : TMakeDirectory;
@ -50,23 +48,28 @@ type
FileSize : TFileSize; FileSize : TFileSize;
PathValid : TPathValid; PathValid : TPathValid;
end; end;
PVFSDevice = ^TVFSDevice;
TVFSFile = record TVFSFile = record
ReadFile : TReadFile; ReadFile : TReadFile;
WriteFile : TWriteFile; WriteFile : TWriteFile;
end; end;
PVFSFile = ^TVFSFile;
TVFSMount = record TVFSMount = record
Path : pchar; Path : pchar;
ObjectType : TObjectType; ObjectType : TObjectType;
Reference : void; Reference : void;
end; end;
PVFSMount = ^TVFSMount;
PVFSObject = ^TVFSObject;
TVFSObject = record TVFSObject = record
Parent : PVFSObject;
ObjectName : pchar;
ObjectType : TObjectType; ObjectType : TObjectType;
Reference : void; Reference : void;
end; end;
PVFSObject = ^TVFSObject;
var var
VirtualFileSystem : PHashMap; Root : PVFSObject;
CurrentDirectory : pchar = nil; CurrentDirectory : pchar = nil;
procedure init(); procedure init();
@ -91,13 +94,196 @@ uses
{ Internal Functions } { 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 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 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');
exit;
end;
Case NewObj^.ObjectType of
otVDIRECTORY,otMOUNT:begin
Obj:= NewObj;
end;
else begin
Obj:= NewObj;
tracer.push_trace('vfs.GetObjectFromPath.shortexit');
Break;
end;
end;
end;
end;
GetObjectFromPath:= Obj;
tracer.push_trace('vfs.GetObjectFromPath.exit');
end;
Procedure ChangeCurrentDirectoryValue(new : pchar); Procedure ChangeCurrentDirectoryValue(new : pchar);
begin begin
tracer.push_trace('vfs.ChangeCurrentDirectoryValue.enter');
if CurrentDirectory <> nil then kfree(void(CurrentDirectory)); if CurrentDirectory <> nil then kfree(void(CurrentDirectory));
CurrentDirectory:= nil; CurrentDirectory:= nil;
CurrentDirectory:= stringCopy(new); CurrentDirectory:= stringCopy(new);
tracer.push_trace('vfs.ChangeCurrentDirectoryValue.exit');
end; 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;
{ Filesystem Functions } { Filesystem Functions }
@ -149,8 +335,52 @@ end;
{ VFS Functions } { VFS Functions }
function newVirtualDirectory(Path : pchar) : TError; function newVirtualDirectory(Path : pchar) : TError;
begin var
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;
if Path[0] = '/' then AbsPath:= stringCopy(Path) else begin
AbsPath:= StringConcat(CurrentDirectory, Path);
end;
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; end;
function getWorkingDirectory : pchar; function getWorkingDirectory : pchar;
@ -160,12 +390,95 @@ end;
{ Terminal Commands } { Terminal Commands }
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
obj : PVFSObject;
begin
tracer.push_trace('vfs.VFS_COMMAND_CD.enter');
obj:= GetObjectFromPath('/disk/test/myfolder');
if obj <> nil then writestringlnWND(getAbsolutePath(obj),getTerminalHWND);
tracer.push_trace('vfs.VFS_COMMAND_CD.exit');
end;
{ Init } { Init }
procedure init(); procedure init();
var
ht : PHashMap;
obj : PVFSObject;
rel : pchar;
begin begin
VirtualFileSystem:= hashmap.new; tracer.push_trace('vfs.init.enter');
Root:= createVirtualDirectory();
Root^.Parent:= nil;
Root^.ObjectName:= stringCopy('/');
ChangeCurrentDirectoryValue('/'); ChangeCurrentDirectoryValue('/');
newVirtualDirectory('/dev');
newVirtualDirectory('/home');
newVirtualDirectory('/disk');
// newVirtualDirectory('/disk/test');
// newVirtualDirectory('/disk/test/myfolder');
// rel:= makeRelative('/disk/SDA/mydirectory/myfile', '/disk/SDA');
// if rel <> nil then outputln('VFS', rel) else outputln('VFS', 'REL IS NULL!');
// while true do begin end;
terminal.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
terminal.registerCommand('CD', @VFS_COMMAND_CD, 'Set 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, 'VFile', void(newDummyObject(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)
tracer.push_trace('vfs.init.exit');
end; end;
end. end.

View File

@ -138,8 +138,37 @@ begin
end; end;
function stringContains(str : pchar; sub : pchar) : boolean; function stringContains(str : pchar; sub : pchar) : boolean;
var
strEnd, subEnd, i, j, count : uint32;
begin begin
stringContains:= false; stringContains:= false;
if stringEquals(str,sub) then begin
stringContains:= true;
exit;
end;
strEnd:= stringSize(str)-1;
subEnd:= stringSize(sub)-1;
if strEnd < subEnd then exit;
for i:=0 to strEnd do begin
if str[i] = sub[0] then begin
count:= 0;
for j:=0 to subEnd do begin
if (i+j) > strEnd then
exit;
if str[i+j] = sub[j] then begin
inc(count)
end else begin
count:= 0;
break;
end;
end;
if count > 0 then begin
stringContains:= true;
exit;
end;
end;
end;
end; end;
function stringToInt(str : pchar) : uint32; function stringToInt(str : pchar) : uint32;