<<>> <> <> <> <<>> DIRECTORY Basics USING [ShortNumber, LongNumber], BasicTime USING [FromNSTime, GMT, OutOfRange], CrRPC USING [GetCard16, GetCard32], IO USING [STREAM], FilingAttributesP10V5 USING [Attribute, AttributeSequence, AttributeSequenceObject, AttributeValue, AttributeValueObject, InterpretedAttributeType], RefText USING [InlineAppendChar, ObtainScratch, ReleaseScratch], Rope USING [FromRefText, ROPE], XNSFilingOps USING [Info], XNSFilingPrivate USING [ ]; XNSFilingBDTImpl: CEDAR MONITOR IMPORTS BasicTime, CrRPC, RefText, Rope EXPORTS XNSFilingPrivate ~ { OPEN FilingAttributesP10V5; ROPE: TYPE ~ Rope.ROPE; FileID: TYPE ~ ARRAY [0..5) OF CARDINAL; FileType: TYPE ~ RECORD [CARD32]; Version: TYPE ~ RECORD [CARD32]; Interpreted: TYPE ~ InterpretedAttributeType[checksum..subtreeSizeLimit]; InterpretedRange: TYPE ~ CARD32[Interpreted.FIRST.ORD..Interpreted.LAST.ORD]; GetAttributeValue: PROC [in: IO.STREAM] RETURNS [attributeValue: AttributeValue] ~ { len: CARDINAL ~ CrRPC.GetCard16[in]; attributeValue _ NEW[AttributeValueObject[len]]; FOR j: CARDINAL IN [0..len) DO attributeValue.body[j] _ CrRPC.GetCard16[in]; ENDLOOP; }; GetAttribute: PROC [in: IO.STREAM] RETURNS [attribute: Attribute] ~ { attribute.type _ CrRPC.GetCard32[in]; attribute.value _ GetAttributeValue[in]; }; GetAttributeSequence: PROC [in: IO.STREAM] RETURNS [attributeSequence: AttributeSequence] ~ { length: CARDINAL ~ CrRPC.GetCard16[in]; attributeSequence _ NEW[AttributeSequenceObject[length]]; FOR i: CARDINAL IN [0..length) DO attributeSequence.body[i] _ GetAttribute[in]; ENDLOOP; }; InfoFromAttributeStream: PUBLIC PROC [in: IO.STREAM] RETURNS [info: XNSFilingOps.Info] ~ { length: CARDINAL ~ CrRPC.GetCard16[in]; FOR i: CARDINAL IN [0..length) DO Get32: PROC RETURNS [num: CARD32] = INLINE { temp: Basics.LongNumber; len: CARDINAL ~ CrRPC.GetCard16[in]; IF ( len # 2 ) THEN ERROR; temp.hi _ CrRPC.GetCard16[in]; temp.lo _ CrRPC.GetCard16[in]; num _ temp.lc; }; attribute: Attribute; attribute.type _ CrRPC.GetCard32[in]; <> IF ( NOT attribute.type IN InterpretedRange ) THEN { -- not one we are looking for so skip it len: CARDINAL ~ CrRPC.GetCard16[in]; FOR j: CARDINAL IN [0..len) DO [] _ CrRPC.GetCard16[in]; ENDLOOP; } ELSE { kind: Interpreted ~ VAL[attribute.type]; SELECT kind FROM createdOn => { temp: CARD32 ~ Get32[]; info.created _ BasicTime.FromNSTime[temp ! BasicTime.OutOfRange => CONTINUE]; }; dataSize => info.bytes _ Get32[]; fileID => { len: CARDINAL ~ CrRPC.GetCard16[in]; IF ( len # 5 ) THEN ERROR; FOR i: CARDINAL IN [0 .. 5) DO info.fID[i] _ CrRPC.GetCard16[in]; ENDLOOP; }; isDirectory => { len: CARDINAL ~ CrRPC.GetCard16[in]; IF ( len # 1 ) THEN ERROR; info.isDir _ IF ( CrRPC.GetCard16[in] = 1 ) THEN TRUE ELSE FALSE; }; numberOfChildren => { len: CARDINAL ~ CrRPC.GetCard16[in]; IF ( len = 1 ) THEN info.numKids _ CrRPC.GetCard16[in]; }; pathname => { length: CARDINAL ~ CrRPC.GetCard16[in]; word, len: NAT _ 0; temp: Basics.ShortNumber; P: PROC [l: NAT] RETURNS [c: CHAR] ~ INLINE { IF ( l MOD 2 ) = 0 THEN { temp.sc _ CrRPC.GetCard16[in]; word _ word.SUCC; c _ VAL[temp.hi] } ELSE { c _ VAL[temp.lo] }; }; pathName: REF TEXT; len _ CrRPC.GetCard16[in]; pathName _ RefText.ObtainScratch[len]; word _ word.SUCC; FOR i: NAT IN [0..len) DO char: CHAR ~ P[i]; pathName _ RefText.InlineAppendChar[pathName, char]; ENDLOOP; IF ( word # length ) THEN ERROR; info.pathName _ Rope.FromRefText[pathName]; RefText.ReleaseScratch[pathName]; }; type => info.fileType _ Get32[]; version => { len: CARDINAL ~ CrRPC.GetCard16[in]; IF ( len # 1 ) THEN ERROR; info.version _ CrRPC.GetCard16[in]; }; ENDCASE => { -- not one we are looking for so skip it len: CARDINAL ~ CrRPC.GetCard16[in]; FOR j: CARDINAL IN [0..len) DO [] _ CrRPC.GetCard16[in]; ENDLOOP; }; }; ENDLOOP; }; }.