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:
parent
2b73fa4f44
commit
d642eafe24
@ -3,12 +3,12 @@ unit vfs;
|
||||
interface
|
||||
|
||||
uses
|
||||
hashmap, strings, lmemorymanager;
|
||||
hashmap, strings, lmemorymanager, lists, tracer, console;
|
||||
|
||||
type
|
||||
TOpenMode = (omReadOnly, omWriteOnly, omReadWrite);
|
||||
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;
|
||||
TIsPathValid = (pvInvalid, pvFile, pvDirectory);
|
||||
|
||||
@ -24,10 +24,7 @@ type
|
||||
TGetDirectories = function(Handle : uint32; Path : pchar) : PHashMap;
|
||||
TPathValid = function(Handle : uint32; Path : pchar) : TIsPathValid;
|
||||
|
||||
TObjectType = (otVDIRECTORY, otDIRECTORY, otDEVICE, otFILE, otMOUNT);
|
||||
TVFSVDirectory = record
|
||||
Contents : PHashMap;
|
||||
end;
|
||||
TObjectType = (otVDIRECTORY, otDRIVE, otDEVICE, otVFILE, otMOUNT, otDIRECTORY, otFILE);
|
||||
TVFSDrive = record
|
||||
DriveHandle : uint32;
|
||||
MakeDirectory : TMakeDirectory;
|
||||
@ -39,6 +36,7 @@ type
|
||||
FileSize : TFileSize;
|
||||
PathValid : TPathValid;
|
||||
end;
|
||||
PVFSDrive = ^TVFSDrive;
|
||||
TVFSDevice = record
|
||||
DeviceHandle : uint32;
|
||||
MakeDirectory : TMakeDirectory;
|
||||
@ -50,23 +48,28 @@ type
|
||||
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;
|
||||
PVFSObject = ^TVFSObject;
|
||||
|
||||
var
|
||||
VirtualFileSystem : PHashMap;
|
||||
Root : PVFSObject;
|
||||
CurrentDirectory : pchar = nil;
|
||||
|
||||
procedure init();
|
||||
@ -91,13 +94,196 @@ uses
|
||||
|
||||
{ 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);
|
||||
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;
|
||||
|
||||
{ Filesystem Functions }
|
||||
|
||||
@ -149,8 +335,52 @@ end;
|
||||
{ VFS Functions }
|
||||
|
||||
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;
|
||||
|
||||
function getWorkingDirectory : pchar;
|
||||
@ -160,12 +390,95 @@ end;
|
||||
|
||||
{ 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 }
|
||||
|
||||
procedure init();
|
||||
var
|
||||
ht : PHashMap;
|
||||
obj : PVFSObject;
|
||||
rel : pchar;
|
||||
|
||||
begin
|
||||
VirtualFileSystem:= hashmap.new;
|
||||
tracer.push_trace('vfs.init.enter');
|
||||
|
||||
Root:= createVirtualDirectory();
|
||||
Root^.Parent:= nil;
|
||||
Root^.ObjectName:= stringCopy('/');
|
||||
|
||||
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.
|
@ -138,8 +138,37 @@ begin
|
||||
end;
|
||||
|
||||
function stringContains(str : pchar; sub : pchar) : boolean;
|
||||
var
|
||||
strEnd, subEnd, i, j, count : uint32;
|
||||
|
||||
begin
|
||||
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;
|
||||
|
||||
function stringToInt(str : pchar) : uint32;
|
||||
|
Loading…
x
Reference in New Issue
Block a user