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