-- 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