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