<<>> <> <> <> <<>> 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; }; }.