-- DirectoryColdImpl.mesa (last edited by: Keith on: December 24, 1980 10:37 AM)
DIRECTORY
Ascii USING [BEL],
CommonSoftwareFileTypes USING [tDirectory],
DCSFileTypes USING [tLeaderPage],
Directory,
DirectoryFiles USING [directoryCache, DoneWith, GetDirectoryCache],
DirectoryInternal,
DirectoryProps USING [SetCreateDate, ValidLP],
DirectoryTrees USING [BTreeDelete, BTreeInsert, MoveLongString],
Environment USING [wordsPerPage],
File USING [Capability, Create, GetSize, LimitPermissions, MakePermanent, nullCapability, PageCount, read, Unknown],
Space USING [Create, CreateUniformSwapUnits, Delete, ForceOut, Handle, LongPointer, Map, Unmap, virtualMemory],
Volume USING [GetAttributes, ID, SetRootFile, Unknown];
DirectoryColdImpl: MONITOR LOCKS DirectoryInternal.DirectoryLock
IMPORTS Directory, DirectoryInternal, DirectoryFiles, DirectoryProps, DirectoryTrees, File, Space, Volume
EXPORTS Directory
SHARES Directory, File =
BEGIN
eType: Directory.ErrorType;
-- entry procedures
CreateSystemDirectory: PUBLIC ENTRY PROC [volume: Volume.ID] =
-- Create the root, system directories and the volume directory tree
BEGIN
ENABLE UNWIND => NULL;
space: Space.Handle;
pPage: DirectoryInternal.DirectoryPageHandle;
dirDesc: DirectoryInternal.DirectoryDescriptor;
pDT: DirectoryInternal.PDT;
pDTNode: DirectoryInternal.PDTNode;
rootCap, sysCap, treeCap: File.Capability;
sysDirWithBEL: STRING ← [7];
pSpace: LONG POINTER TO UNSPECIFIED;
isRoot: BOOLEAN ← TRUE;
rootCap ← Volume.GetAttributes[volume].rootFile;
[] ← File.GetSize[rootCap ! File.Unknown => {isRoot ← FALSE; CONTINUE}];
IF isRoot THEN
IF DirectoryProps.ValidLP[rootCap] THEN RETURN WITH ERROR Directory.Error[fileAlreadyExists];
DirectoryTrees.MoveLongString[to: sysDirWithBEL, from: "SysDir"L];
sysDirWithBEL[sysDirWithBEL.length] ← Ascii.BEL;
sysDirWithBEL.length ← sysDirWithBEL.length + 1;
space ← Space.Create[MAX[DirectoryInternal.initDirSize, DirectoryInternal.initDTSize], Space.virtualMemory];
Space.CreateUniformSwapUnits[DirectoryInternal.swapUnitSize, space];
pSpace ← Space.LongPointer[space];
rootCap ← File.Create[
volume, DirectoryInternal.initDirSize, CommonSoftwareFileTypes.tDirectory !
Volume.Unknown => {eType ← volumeNotFound; GOTO AnError}];
-- Initialize the root directory to the system directory and the directory tree
Space.Map[space, [rootCap, DirectoryInternal.leaderPageSize]];
pPage ← pSpace;
pPage.parent ← pPage.lastPointer ← DirectoryInternal.nilPagePointer;
pPage.size ← DirectoryInternal.emptySize;
pPage.free ← FALSE;
pPage.top ← FIRST[DirectoryInternal.PagePointer];
pPage ← pPage + Environment.wordsPerPage;
FOR x: File.PageCount ← DirectoryInternal.leaderPageSize+1, x + 1 UNTIL x = DirectoryInternal.initDirSize DO
pPage.free ← TRUE; pPage ← pPage + Environment.wordsPerPage; ENDLOOP;
Volume.SetRootFile[volume, rootCap];
File.MakePermanent[rootCap];
DirectoryProps.SetCreateDate[rootCap, "RootDir"L, File.nullCapability];
pPage ← pSpace;
dirDesc ←
[base: pPage, top: pPage.top, size: DirectoryInternal.initDirSize - DirectoryInternal.leaderPageSize, space: space];
sysCap ← File.Create[volume, DirectoryInternal.initDirSize, CommonSoftwareFileTypes.tDirectory];
treeCap ← File.Create[volume, DirectoryInternal.initDTSize, DCSFileTypes.tLeaderPage];
[] ← DirectoryTrees.BTreeInsert[@dirDesc, sysDirWithBEL, sysCap];
[] ← DirectoryTrees.BTreeInsert[
@dirDesc, "Volume.DirectoryTree", File.LimitPermissions[
treeCap, File.read]];
File.MakePermanent[sysCap];
File.MakePermanent[treeCap];
Space.Unmap[space];
Space.Map[space, [sysCap, DirectoryInternal.leaderPageSize]]; -- Initialize the system directory to empty
pPage ← pSpace;
pPage.parent ← pPage.lastPointer ← DirectoryInternal.nilPagePointer;
pPage.size ← DirectoryInternal.emptySize;
pPage.free ← FALSE;
pPage.top ← FIRST[DirectoryInternal.PagePointer];
pPage ← pPage + Environment.wordsPerPage;
FOR x: File.PageCount ← DirectoryInternal.leaderPageSize+1, x + 1 UNTIL x = DirectoryInternal.initDirSize DO
pPage.free ← TRUE; pPage ← pPage + Environment.wordsPerPage; ENDLOOP;
DirectoryProps.SetCreateDate[sysCap, "SysDir"L, rootCap];
Space.Unmap[space];
Space.Map[space, [treeCap, DirectoryInternal.leaderPageSize]]; -- Initialize the Directory Tree
pDT ← pSpace;
-- first entry contains pointers to tree, free and full cap of tree
pDTNode ← FIRST[DirectoryInternal.PDTNode];
pDT[pDTNode].name ←
[length: 0, maxlength: Directory.maxDirectoryNameLength, text:];
pDT[pDTNode].cap ← treeCap;
pDT[pDTNode].son ← pDTNode + SIZE[DirectoryInternal.DTNode];
pDT[pDTNode].bro ← pDTNode + 3*SIZE[DirectoryInternal.DTNode];
pDT[pDTNode].level ← LAST[CARDINAL];
pDTNode ← pDTNode + SIZE[DirectoryInternal.DTNode];
-- second describes root directory
pDT[pDTNode].name ←
[length: 0, maxlength: Directory.maxDirectoryNameLength, text:];
DirectoryTrees.MoveLongString[to: @pDT[pDTNode].name, from: "RootDir"L];
pDT[pDTNode].son ← pDTNode + SIZE[DirectoryInternal.DTNode];
pDT[pDTNode].bro ← pDTNode;
pDT[pDTNode].cap ← rootCap;
pDT[pDTNode].level ← 0;
pDTNode ← pDTNode + SIZE[DirectoryInternal.DTNode];
-- third describes the system directory
pDT[pDTNode].name ←
[length: 0, maxlength: Directory.maxDirectoryNameLength, text:];
DirectoryTrees.MoveLongString[to: @pDT[pDTNode].name, from: "SysDir"L];
pDT[pDTNode].son ← pDTNode;
pDT[pDTNode].bro ←
FIRST[DirectoryInternal.PDTNode] + SIZE[DirectoryInternal.DTNode];
pDT[pDTNode].cap ← sysCap;
pDT[pDTNode].level ← 1; -- rest are free nodes
FOR x: CARDINAL ← 3, x + 1 UNTIL
x = (DirectoryInternal.initDTSize-DirectoryInternal.leaderPageSize)*Environment.wordsPerPage
/SIZE[DirectoryInternal.DTNode] DO
pDTNode ← pDTNode + SIZE[DirectoryInternal.DTNode];
pDT[pDTNode].name ←
[length: 0, maxlength: Directory.maxDirectoryNameLength, text:];
pDT[pDTNode].bro ← pDTNode + SIZE[DirectoryInternal.DTNode]
ENDLOOP;
pDT[pDTNode].bro ← DirectoryInternal.pDTnil;
DirectoryProps.SetCreateDate[treeCap, "Volume.DirectoryTree"L, rootCap];
Space.Unmap[space];
Space.Delete[space];
RETURN
EXITS AnError => RETURN WITH ERROR Directory.Error[eType];
END;
Insert: PUBLIC ENTRY PROC [
parent: File.Capability, fileName: LONG STRING, file: File.Capability]
RETURNS [BOOLEAN] = -- Special Insert for the Scavenger
BEGIN
ENABLE UNWIND => NULL;
pDD: LONG POINTER TO DirectoryInternal.DirectoryDescriptor ← NIL;
ok, noRoom: BOOLEAN;
BEGIN
ENABLE Directory.Error => {eType ← type; GOTO AnError};
IF fileName = NIL THEN RETURN WITH ERROR Directory.Error[invalidFileName];
pDD ← @(DirectoryFiles.directoryCache[DirectoryFiles.GetDirectoryCache[parent]].dir);
[ok: ok, noRoom: noRoom] ← DirectoryTrees.BTreeInsert[pDD, fileName, file];
IF noRoom THEN {eType ← notImplemented; GOTO AnError};
IF ~ ok THEN {DirectoryFiles.DoneWith[pDD]; RETURN [FALSE]};
Space.ForceOut[pDD.space];
DirectoryFiles.DoneWith[pDD];
RETURN [TRUE]
EXITS AnError => {DirectoryFiles.DoneWith[pDD]; RETURN WITH ERROR Directory.Error[eType]};
END;
END;
Remove: PUBLIC ENTRY PROC [
parent: File.Capability, fileName: LONG STRING, file: File.Capability]
RETURNS [BOOLEAN] = -- Special Remove for the Scavenger
BEGIN
ENABLE UNWIND => NULL;
pDD: LONG POINTER TO DirectoryInternal.DirectoryDescriptor ← NIL;
actualFile: File.Capability;
exists, sd: BOOLEAN;
BEGIN
ENABLE Directory.Error => {eType ← type; GOTO AnError};
IF fileName = NIL THEN RETURN WITH ERROR Directory.Error[invalidFileName];
pDD ← @(DirectoryFiles.directoryCache[DirectoryFiles.GetDirectoryCache[parent]].dir);
[ok: exists, cap: actualFile, isSD: sd] ← DirectoryTrees.BTreeDelete[pDD, fileName, FALSE];
IF ~exists OR (file # actualFile) THEN {DirectoryFiles.DoneWith[pDD]; RETURN [FALSE]};
Space.ForceOut[pDD.space];
DirectoryFiles.DoneWith[pDD];
RETURN [TRUE]
EXITS AnError => {DirectoryFiles.DoneWith[pDD]; RETURN WITH ERROR Directory.Error[eType]};
END;
END;
END.
Log
Time: December 24, 1980 11:00 AM By: Keith Action: Created file from DirectoryFilesImpl