<> <> <> <<>> <<>> <> <<>> DIRECTORY Basics USING [ByteBlt], Random USING [Create, NextInt, RandomStream], RefText USING [AppendChar, AppendRope, New], Rope USING [Equal, Find, FromRefText, Length, ROPE], YggDID USING [DID, ValidateDID], YggDummyRPC USING [unencrypted], YggEnvironment USING [Outcome, TransID], YggIndex USING [], YggNav USING [ErrorDesc, LinkList], YggRep USING [AccurateGMT, AccurateGMTRep, Attribute, Bits, BitsRep, BytesFromBits, BytesToBits, date, DocType, float, int, lastReservedDocType, rope, shortRope, SetSizeOfBits, TypedPrimitiveElement, uninterpretedBytes, VDoc, VolatizeFromDID], YggTransaction USING [Check, Create, Finish]; YggNavImpl: CEDAR MONITOR IMPORTS Basics, Random, RefText, Rope, YggDID, YggRep, YggTransaction EXPORTS YggDID, YggNav ~ BEGIN <> ROPE: TYPE = Rope.ROPE; Error: PUBLIC ERROR [error: YggNav.ErrorDesc] = CODE; RootPath: PUBLIC ROPE _ "/tregonsee"; RootPathToRoots: PUBLIC ROPE _ "/tregonsee"; randomCharStream: Random.RandomStream; DID: PUBLIC TYPE ~ REF DIDRep; DIDRep: PUBLIC TYPE ~ ROPE; <> <> <> <<>> StartTransaction: PUBLIC PROC RETURNS [trans: YggEnvironment.TransID] ~ { <> trans _ YggTransaction.Create[conversation: YggDummyRPC.unencrypted, createLocalWorker: TRUE]; }; <<>> EndTransaction: PUBLIC PROC [trans: YggEnvironment.TransID, commit: BOOL] RETURNS [ok: BOOL _ TRUE] ~ { <> outcome: YggEnvironment.Outcome; [outcome: outcome] _ YggTransaction.Finish[conversation: YggDummyRPC.unencrypted, transID: trans, requestedOutcome: IF commit THEN commit ELSE abort, continue: FALSE]; IF outcome = commit THEN RETURN [TRUE] ELSE RETURN [FALSE]; }; <<>> CheckTransaction: PUBLIC PROC [trans: YggEnvironment.TransID] RETURNS [ok: BOOL _ TRUE] ~ { <> outcome: YggEnvironment.Outcome; [outcome: outcome] _ YggTransaction.Check[transID: trans]; IF outcome = unknown THEN RETURN [TRUE] ELSE RETURN [FALSE]; }; <> <> <<>> GetRoots: PUBLIC PROC RETURNS [roots: LIST OF DID] ~ { <> enumProc: PROC [localName, symbolicName: ROPE] RETURNS [continue: BOOL _ TRUE] = { did: DID; did _ NEW[DIDRep]; did^ _ symbolicName; roots _ CONS[did, roots]; }; EnumerateSymbolicLinksInDirectory [directory: RootPathToRoots, proc: enumProc]; }; <<>> AddRoot: PUBLIC PROC [did: DID] RETURNS [ok: BOOL] ~ { <> tries: INT _ 0; nameSize: INT _ 4; unixdid: REF TEXT ~ UnixStringFromRope[did^]; name1: CARD ~ LOOPHOLE[unixdid, CARD]+UNITS[TEXT[0]]; IF ~YggDID.ValidateDID[did] THEN RETURN [FALSE]; DO sl: INT; symname: REF TEXT _ RefText.New[nameSize]; unixSymname: REF TEXT _ NIL; name2: CARD; FOR charNo: INT IN [0..nameSize) DO [] _ RefText.AppendChar[to: symname, from: Random.NextInt[] + 'a]; ENDLOOP; unixSymname _ UnixStringFromRope[""]; name2 _ LOOPHOLE[unixSymname, CARD]+UNITS[TEXT[0]]; sl _ Symlink[name1, name2]; IF sl = 0 THEN EXIT; tries _ tries + 1; IF tries MOD 250 = 0 THEN nameSize _ MIN[50, nameSize + 1]; ENDLOOP; }; <<>> RemoveRoot: PUBLIC PROC [did: DID] RETURNS [ok: BOOL] ~ { <> enumProc: PROC [localName, symbolicName: ROPE] RETURNS [continue: BOOL _ TRUE] = { IF Rope.Equal[did^, symbolicName] THEN { nameToDelete _ localName; continue _ FALSE; }; }; nameToDelete: ROPE _ NIL; EnumerateSymbolicLinksInDirectory [directory: RootPathToRoots, proc: enumProc]; IF nameToDelete # NIL THEN { unixNameToDelete: REF TEXT ~ UnixStringFromRope[nameToDelete]; [] _ Unlink[LOOPHOLE[unixNameToDelete, CARD]+UNITS[TEXT[0]]]; }; }; <> GetTypeOfContents: PUBLIC PROC [trans: YggEnvironment.TransID, did: YggDID.DID] RETURNS [YggRep.DocType] ~ { <> <> document: YggRep.VDoc; document _ YggRep.VolatizeFromDID[trans, did]; RETURN[document.contents.docType]; }; <<>> GetUninterpretedContents: PUBLIC UNSAFE PROC [trans: YggEnvironment.TransID, did: DID, firstByte: CARD, byteCount: CARD, to: LONG POINTER] RETURNS [bytesMoved: CARD] ~ { <> <> document: YggRep.VDoc; document _ YggRep.VolatizeFromDID[trans, did]; IF document.contents.docType # YggRep.uninterpretedBytes AND document.contents.docType <= YggRep.lastReservedDocType THEN ERROR Error[[$invalidReservedType, "Attempt to access a TypedPrimitiveElement with reserved type as uninterpreted"]]; YggRep.BytesFromBits[bits: document.contents.bits, startByte: firstByte, block: [base: LOOPHOLE[to], startIndex: 0, count: byteCount]]; }; <<>> GetContents: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [contents: YggRep.TypedPrimitiveElement] ~ { <> <> document: YggRep.VDoc; document _ YggRep.VolatizeFromDID[trans, did]; RETURN[document.contents]; }; <<>> SetUninterpretedContents: PUBLIC UNSAFE PROC [trans: YggEnvironment.TransID, did: YggDID.DID, firstByte: CARD, byteCount: CARD, from: LONG POINTER] RETURNS [bytesMoved: CARD] ~ { <> <> document: YggRep.VDoc; newRef: BOOL; newBits: YggRep.Bits; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; IF document.contents.docType # YggRep.uninterpretedBytes AND document.contents.docType <= YggRep.lastReservedDocType THEN ERROR Error[[$invalidReservedType, "Attempt to set a TypedPrimitiveElement with reserved type as uninterpreted"]]; [newRef: newRef, newBits: newBits] _ YggRep.BytesToBits[bits: document.contents.bits, startByte: firstByte, block: [base: LOOPHOLE[from], startIndex: 0, count: byteCount]]; IF newRef THEN document.contents.bits _ newBits; RETURN[byteCount]; }; <<>> SetContents: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, contents: YggRep.TypedPrimitiveElement] ~ { <> <> document: YggRep.VDoc; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; document.contents _ contents; }; <<>> SetSize: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, size: CARD] ~ { <> <> document: YggRep.VDoc; newRef: BOOL; newBits: YggRep.Bits; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; IF document.contents.docType # YggRep.uninterpretedBytes AND document.contents.docType <= YggRep.lastReservedDocType THEN ERROR Error[[$invalidReservedType, "Attempt to set a TypedPrimitiveElement with reserved type as uninterpreted"]]; [newRef: newRef, newBits: newBits] _ YggRep.SetSizeOfBits[bits: document.contents.bits, size: size]; IF newRef THEN document.contents.bits _ newBits; }; <<>> <> GetProperty: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, propertyName: ROPE] RETURNS [propertyExists: BOOL, property: YggRep.Attribute] ~ { <> <> }; <<>> GetAllProperties: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [properties: LIST OF YggRep.Attribute] ~ { <> <> }; <<>> ListAllProperties: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [propertyNames: LIST OF ROPE] ~ { <> <> }; <<>> SetProperty: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, propertyName: ROPE, property: YggRep.Attribute] ~ { <> <> }; <<>> <> <> <<>> ConstructIntTPE: PUBLIC PROC [int: INT32] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { <> <> ri: REF INT32; ri _ NEW[INT32 _ int]; property _ [YggRep.int, ri]; }; <<>> ConstructFloatTPE: PUBLIC PROC [float: REAL32] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { <> rReal: REF REAL32; rReal _ NEW[REAL32 _ float]; property _ [YggRep.float, rReal]; }; <<>> ConstructDateTPE: PUBLIC PROC [date: YggRep.AccurateGMTRep] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { <> rAccurateGMT: YggRep.AccurateGMT; rAccurateGMT _ NEW[YggRep.AccurateGMTRep _ date]; property _ [YggRep.date, rAccurateGMT]; }; <<>> ConstructShortRopeTPE: PUBLIC PROC [rope: ROPE] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { <> <> IF Rope.Find[rope, "\000"] = -1 THEN { property _ [YggRep.shortRope, rope]; } ELSE ERROR Error[[$shortRopeWithNulls, "Rope has nulls"]]; }; <<>> ConstructRopeTPE: PUBLIC PROC [rope: ROPE] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { <> property _ [YggRep.rope, rope]; }; <<>> ConstructUninterpretedBytesTPE: PUBLIC PROC [docType: YggRep.DocType, bytes: LONG POINTER, size: CARD] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { <> <> nBytes: CARD; rBits: REF YggRep.BitsRep; IF docType # YggRep.uninterpretedBytes AND docType <= YggRep.lastReservedDocType THEN ERROR Error[[$invalidReservedType, "Attempt to create a TypedPrimitiveElement with reserved type"]]; rBits _ NEW[YggRep.BitsRep[size]]; rBits.validBytes _ size; TRUSTED {nBytes _ Basics.ByteBlt[ from: [blockPointer: bytes, startIndex: 0, stopIndexPlusOne: size], to: [blockPointer: LOOPHOLE[rBits, POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: size]]; }; IF nBytes # size THEN ERROR; property _ [docType, rBits]; }; <> GetTypedOutlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, linkType: ROPE] RETURNS [LIST OF DID _ NIL] ~ { <> <> }; <<>> GetAllOutlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [LIST OF YggNav.LinkList _ NIL] ~ { <> <> }; <<>> GetTypedInlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, linkType: ROPE] RETURNS [LIST OF DID _ NIL] ~ { <> <> }; <<>> GetAllInlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [LIST OF YggNav.LinkList _ NIL] ~ { <> <> }; <<>> SnapLink: PUBLIC PROC [trans: YggEnvironment.TransID, fromDID: DID, toDID: DID, linkType: ROPE] RETURNS [linkDID: DID _ NIL] ~ { <> <> }; <> GetDefaultContainer: PUBLIC PROC [trans: YggEnvironment.TransID] RETURNS [DID _ NIL] ~ { <> <> }; <<>> SetDefaultContainer: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] ~ { <> <> }; <<>> AddToContainer: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, containerDID: DID] ~ { <> <> }; <<>> RemoveFromContainer: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, containerDID: DID] RETURNS [ok: BOOL _ TRUE] ~ { <> <> }; <<>> GetObjectsInContainer: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID] RETURNS [LIST OF DID _ NIL] ~ { <> <> }; <<>> AddContainerToContainer: PUBLIC PROC [trans: YggEnvironment.TransID, subcontainerDID: DID, containerDID: DID] ~ { <> <> }; <<>> RemoveContainerFromContainer: PUBLIC PROC [trans: YggEnvironment.TransID, subcontainerDID: DID, containerDID: DID] RETURNS [ok: BOOL _ TRUE] ~ { <> <> }; <<>> GetContainersInContainer: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID] RETURNS [LIST OF DID _ NIL] ~ { <> <> }; <> CreateObject: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID] RETURNS [did: DID _ NIL] ~ { <> <> }; <<>> RemoveObject: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] ~ { <> <> }; <<>> <> CreateIndex: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID, pattern: ROPE] RETURNS [did: DID _ NIL] ~ { <> <> }; <<>> ListIndexPatterns: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID] RETURNS [patterns: LIST OF ROPE _ NIL] ~ { <> <> }; <<>> RemoveIndex: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID, pattern: ROPE] RETURNS [ok: BOOL _ TRUE] ~ { <> <> }; <> <> <> DIR: TYPE ~ PACKED RECORD [ ddFd: INT, ddLoc: INT, ddSize: INT, ddBbase: INT, ddEntno: INT, ddBsize: INT, ddBuf: LONG POINTER TO ARRAY [0..0] OF CHAR ]; direct: TYPE ~ PACKED RECORD [ dFileno: CARD32, dReclen: CARD16, dNamlen: CARD16, dName: LONG POINTER TO ARRAY [0..0] OF CHAR ]; UnixStringFromRope: PROC [rope: ROPE] RETURNS [REF TEXT] ~ { len: INT _ rope.Length[]; rtn: REF TEXT _ RefText.New[len+1]; [] _ RefText.AppendRope[to: rtn, from: rope]; [] _ RefText.AppendChar[to: rtn, from: '\000]; RETURN[rtn]; }; EnumerateSymbolicLinksInDirectory: PROC [directory: ROPE, proc: PROC [localName, symbolicName: ROPE] RETURNS [continue: BOOL _ TRUE]] ~ { dirStream: LONG POINTER TO DIR; cont: BOOL; unixDirName: REF TEXT ~ UnixStringFromRope[directory]; dirStream _ Opendir[LOOPHOLE[unixDirName, CARD]+UNITS[TEXT[0]]]; IF dirStream # NIL THEN { symLinkBuff: REF TEXT _ RefText.New[256]; symLinkResult: REF TEXT _ RefText.New[1024]; resetLen: INT; [] _ RefText.AppendRope[to: symLinkBuff, from: directory]; [] _ RefText.AppendChar[to: symLinkBuff, from: '/]; resetLen _ symLinkBuff.length; DO dirp: LONG POINTER TO direct; cc: INT; symLinkName: ROPE; localName: ROPE; localNameLength: INT; dirp _ Readdir[dirStream]; IF dirp = NIL THEN EXIT; symLinkBuff.length _ resetLen; TRUSTED { localNameLength _ dirp.dNamlen; FOR charNo: INT IN [0..localNameLength] DO [] _ RefText.AppendChar[to: symLinkBuff, from: dirp.dName[charNo]]; ENDLOOP; }; [] _ RefText.AppendChar[to: symLinkBuff, from: '\000]; cc _ Readlink[path: LOOPHOLE[symLinkBuff, CARD] +UNITS[TEXT[0]], buf: LOOPHOLE[symLinkResult, CARD]+UNITS[TEXT[0]], bufsiz: 1023]; IF cc <= 0 THEN LOOP; symLinkResult.length _ cc; symLinkName _ Rope.FromRefText[s: symLinkResult, start: 0, len: cc]; localName _ Rope.FromRefText[s: symLinkBuff, start: 0, len: resetLen + localNameLength]; cont _ proc[localName, symLinkName]; IF ~cont THEN EXIT; ENDLOOP; [] _ Closedir[dirStream]; }; }; <> Symlink: PROC [name1: CARD, name2: CARD] RETURNS [INT] ~ TRUSTED MACHINE CODE { "symlink" }; Opendir: PROC [name: CARD] RETURNS [LONG POINTER TO DIR] ~ TRUSTED MACHINE CODE { "opendir" }; Readdir: PROC [LONG POINTER TO DIR] RETURNS [LONG POINTER TO direct] ~ TRUSTED MACHINE CODE { "readdir" }; Closedir: PROC [LONG POINTER TO DIR] RETURNS [trash: INT] ~ TRUSTED MACHINE CODE { "closedir" }; Readlink: PROC [path: CARD, buf: CARD, bufsiz: INT] RETURNS [cc: INT] ~ TRUSTED MACHINE CODE { "readlink" }; Unlink: PROC [path: CARD] RETURNS [cc: INT] ~ TRUSTED MACHINE CODE { "unlink" }; <> randomCharStream _ Random.Create[range: 26]; END.