<<>> <> <> <> <<>> DIRECTORY Basics USING [LongNumber, ShortNumber], BasicTime USING [FromNSTime, GMT, nullGMT, OutOfRange, ToNSTime], CHNameP2V0 USING [], FilingAttributesP10V5 USING [AccessEntrySequence, AccessList, Attribute, AttributeSequence, AttributeSequenceObject, AttributeValue, AttributeValueObject, FileID, Interpretation, InterpretedAttributeType, nullFileID, Ordering, Position, PositionObject, User], FilingP10V5 USING [allDescendants, Control, ControlSequence, ControlSequenceObject, Direction, Filter, FilterObject, FilterType, PatternFilter, RelationFilter, Scope, ScopeObject, ScopeSequence, ScopeSequenceObject, ScopeType, unlimitedCount], RefText USING [InlineAppendChar, ObtainScratch], Rope USING [FromProc, InlineFetch, Length, ROPE], XNSFilingAttributes USING [Interpreted, InterpretedRange]; XNSFilingAttributeImpl: CEDAR MONITOR IMPORTS BasicTime, RefText, Rope EXPORTS XNSFilingAttributes ~ { OPEN FilingP10V5, FilingAttributesP10V5, XNSFilingAttributes; ROPE: TYPE ~ Rope.ROPE; <> InfoFromAttributeSequence: PUBLIC PROC [attributes: AttributeSequence] RETURNS [vers: CARD _ 0, bytes: INT _ -1, created: BasicTime.GMT _ BasicTime.nullGMT, fileType: CARD _ 0, pathName: REF TEXT _ NIL, fID: FileID _ nullFileID, isDir: BOOL _ FALSE, numKids: CARD _ 0] ~ { FOR i: INT IN [0..attributes.length) DO attribute: Attribute ~ attributes[i]; color: Interpreted; IF ( attribute.type NOT IN InterpretedRange ) THEN LOOP; color _ VAL[attribute.type]; SELECT color FROM createdOn => { temp: CARD32 ~ DecapsulateCard32[attribute.value]; created _ BasicTime.FromNSTime[temp ! BasicTime.OutOfRange => CONTINUE]; }; numberOfChildren => { numKids _ 0; IF ( attribute.value = NIL ) THEN LOOP; IF ( attribute.value.length = 0 ) THEN LOOP; numKids _ DecapsulateCard16[attribute.value]; }; dataSize => { bytes _ DecapsulateCard32[attribute.value] }; fileID => { fID _ DecapsulateFileID[attribute.value] }; isDirectory => { isDir _ DecapsulateBoolean[attribute.value] }; pathname => { pathName _ DecapsulateRefText[attribute.value] }; type => { fileType _ DecapsulateCard32[attribute.value] }; version => { vers _ DecapsulateCard16[attribute.value] }; ENDCASE => NULL; ENDLOOP; }; <> nullAttributes: PUBLIC AttributeSequence _ NEW[AttributeSequenceObject[0]]; nullControls: PUBLIC ControlSequence _ NEW[ControlSequenceObject[0]]; <> BuildScope: PUBLIC PROC [filterType: FilterType, rope: ROPE, type: CARD32] RETURNS [scope: ScopeSequence] = { value: AttributeValue _ EncapsulateRope[rope]; filter: Filter; scope _ NEW[ScopeSequenceObject[4]]; scope[0] _ NEW[ScopeObject.count _ [count[unlimitedCount]]]; scope[1] _ NEW[ScopeObject.depth _ [depth[allDescendants]]]; scope[2] _ NEW[ScopeObject.direction _ [direction[forward]]]; filter _ SELECT filterType FROM matches => NEW [FilterObject.matches _ [matches[matches: [attribute: [type: type, value: value]]] ]], equal => NEW [FilterObject.equal _ [equal[equal: [attribute: [type: type, value: value], interpretation: string]] ]], ENDCASE => NEW [FilterObject.none _ [none[none: [null: 0]] ]]; scope[3] _ NEW [ScopeObject.filter _ [filter[filter: filter]]]; }; BuildAttribute: PUBLIC PROC [name: ROPE, type: CARD32, time: BasicTime.GMT _ BasicTime.nullGMT, timeType: CARD32 _ 0] RETURNS [attributes: AttributeSequence] = { IF time = BasicTime.nullGMT THEN { attributes _ NEW [AttributeSequenceObject[1]]; attributes[0] _ [type: type, value: EncapsulateRope[name]]; RETURN[attributes]; }; attributes _ NEW [AttributeSequenceObject[2]]; attributes[0] _ [type: timeType, value: EncapsulateCard32[BasicTime.ToNSTime[time]]]; attributes[1] _ [type: type, value: EncapsulateRope[name]]; RETURN[attributes]; }; BuildDirectoryAttribute: PUBLIC PROC [nameR: ROPE] RETURNS [attributes: AttributeSequence] = { attributes _ NEW [AttributeSequenceObject[3]]; attributes[0] _ [type: Interpreted.isDirectory.ORD, value: EncapsulateBoolean[TRUE]]; attributes[1] _ [type: Interpreted.name.ORD, value: EncapsulateRope[nameR]]; attributes[2] _ [type: Interpreted.type.ORD, value: EncapsulateCard32[1 -- tDirectory --]]; RETURN[attributes]; }; BuildStoreAttributes: PUBLIC PROC [file: ROPE, vers: CARDINAL, created: BasicTime.GMT] RETURNS [attributes: AttributeSequence] ~ { num: CARDINAL _ IF ( created = BasicTime.nullGMT ) THEN 2 ELSE 3; attributes _ NEW [AttributeSequenceObject[num]]; attributes[0] _ [type: Interpreted.name.ORD, value: EncapsulateRope[file]]; attributes[1] _ [type: Interpreted.version.ORD, value: EncapsulateCard16[vers]]; IF ( created # BasicTime.nullGMT ) THEN { time: CARD32 _ BasicTime.ToNSTime[created]; attributes[2] _ [type: Interpreted.createdOn.ORD, value: EncapsulateCard32[time]]; }; }; <> EncapsulateAccessList: PUBLIC PROC [accessList: AccessList] RETURNS [value: AttributeValue] ~ { value _ NIL; }; DecapsulateAccessList: PUBLIC PROC [value: AttributeValue] RETURNS [accessList: AccessList] ~ { <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <<};>> <> <> }; EncapsulateFileID: PUBLIC PROC [fileID: FileID] RETURNS [value: AttributeValue] ~ { len: CARDINAL ~ 5; value _ NEW[AttributeValueObject[len]]; FOR i: CARDINAL IN [0..len) DO value[i] _ fileID[i]; ENDLOOP; }; DecapsulateFileID: PUBLIC PROC [value: AttributeValue] RETURNS [fileID: FileID] ~ { IF value = NIL THEN ERROR; IF value.length # 5 THEN ERROR; FOR i: CARDINAL IN [0..5) DO fileID[i] _ value[i]; ENDLOOP; }; EncapsulateOrdering: PUBLIC PROC [ordering: Ordering] RETURNS [value: AttributeValue] ~ { value _ NIL; }; DecapsulateOrdering: PUBLIC PROC [value: AttributeValue] RETURNS [ordering: Ordering] ~ { temp: Basics.LongNumber; IF value = NIL THEN ERROR; IF value.length # 4 THEN ERROR; temp.hi _ value[0]; temp.lo _ value[1]; ordering.key _ temp.lc; ordering.ascending _ IF value[2] = 1 THEN TRUE ELSE FALSE; ordering.interpretation _ VAL[value[3]]; }; EncapsulatePosition: PUBLIC PROC [position: Position] RETURNS [value: AttributeValue] ~ { value _ NIL; }; DecapsulatePosition: PUBLIC PROC [value: AttributeValue] RETURNS [position: Position] ~ { length: CARDINAL; IF value = NIL THEN ERROR; IF value.length <= 0 THEN ERROR; length _ value[0]; position _ NEW[PositionObject[length]]; FOR i: CARDINAL IN [0..length) DO position.body[i] _ value[i+1]; ENDLOOP; }; EncapsulateUser: PUBLIC PROC [name: ROPE] RETURNS [value: AttributeValue] ~ { value _ NIL; }; DecapsulateUser: PUBLIC PROC [value: AttributeValue] RETURNS [user: User] ~ { place: NAT _ 0; GetRope: PROC [] RETURNS [r: ROPE] = { temp: Basics.ShortNumber; len, i: NAT _ 0; P: PROC RETURNS[c: CHAR] = { IF i MOD 2 = 0 THEN {temp.sc _ value[place]; place _ place + 1; c _ VAL[temp.hi]} ELSE {c _ VAL[temp.lo]}; i _ i + 1; }; len _ value[place]; place _ place + 1; r _ Rope.FromProc[len: len, p: P]; }; IF value = NIL THEN ERROR; user.organization _ GetRope[]; user.domain _ GetRope[]; user.object _ GetRope[]; }; <> EncapsulateBoolean: PUBLIC PROC [b: BOOL] RETURNS [value: AttributeValue] ~ { len: NAT ~ 1; -- wrapped len value _ NEW [AttributeValueObject[len]]; value[0] _ IF b THEN 1 ELSE 0; }; DecapsulateBoolean: PUBLIC PROC [value: AttributeValue] RETURNS [b: BOOL] ~ { IF value = NIL THEN ERROR; IF value.length # 1 THEN ERROR; b _ IF value[0] = 1 THEN TRUE ELSE FALSE; }; EncapsulateCard16: PUBLIC PROC [i: CARD16] RETURNS [value: AttributeValue] ~ { len: NAT ~ 1; -- wrapped len value _ NEW [AttributeValueObject[len]]; value[0] _ i; }; DecapsulateCard16: PUBLIC PROC [value: AttributeValue] RETURNS [i: CARD16] ~ { IF value = NIL THEN ERROR; IF value.length # 1 THEN ERROR; i _ value[0]; }; EncapsulateCard32: PUBLIC PROC [i: CARD32] RETURNS [value: AttributeValue] ~ { temp: Basics.LongNumber; len: NAT ~ 2; -- wrapped len value _ NEW [AttributeValueObject[len]]; temp.lc _ i; value[0] _ temp.hi; value[1] _ temp.lo; }; DecapsulateCard32: PUBLIC PROC [value: AttributeValue] RETURNS [i: CARD32] ~ { temp: Basics.LongNumber; IF value = NIL THEN ERROR; IF value.length # 2 THEN ERROR; temp.hi _ value[0]; temp.lo _ value[1]; i _ temp.lc; }; EncapsulateRope: PUBLIC PROC [name: ROPE] RETURNS [value: AttributeValue] ~ { len: NAT ~ (name.Length[]+3) / 2; -- wrapped len value _ NEW[AttributeValueObject[len]]; TRUSTED { EncapsulateBytes[@(value.body), name] }; }; DecapsulateRope: PUBLIC PROC [value: AttributeValue] RETURNS [rope: ROPE] ~ { place: NAT _ 0; GetRope: PROC [] RETURNS [r: ROPE] = { temp: Basics.ShortNumber; len, i: NAT _ 0; P: PROC RETURNS[c: CHAR] = { IF i MOD 2 = 0 THEN {temp.sc _ value[place]; place _ place + 1; c _ VAL[temp.hi]} ELSE {c _ VAL[temp.lo]}; i _ i + 1; }; len _ value[place]; place _ place + 1; r _ Rope.FromProc[len: len, p: P]; }; IF value = NIL THEN ERROR; rope _ GetRope[]; }; DecapsulateRefText: PUBLIC PROC [value: AttributeValue] RETURNS [rope: REF TEXT] ~ { place: NAT _ 0; GetRope: PROC [] RETURNS [r: REF TEXT] = { temp: Basics.ShortNumber; len: NAT _ 0; P: PROC [i: NAT] RETURNS[c: CHAR] = { IF i MOD 2 = 0 THEN {temp.sc _ value[place]; place _ place + 1; c _ VAL[temp.hi]} ELSE {c _ VAL[temp.lo]}; }; len _ value[place]; place _ place + 1; r _ RefText.ObtainScratch[len]; FOR i: NAT IN [0 .. len) DO c: CHAR ~ P[i]; r _ RefText.InlineAppendChar[r, c]; ENDLOOP; }; IF value = NIL THEN ERROR; rope _ GetRope[]; }; OpaqueByteObject: TYPE ~ MACHINE DEPENDENT RECORD [ length: CARDINAL, <> body: PACKED ARRAY [0..1000) OF CHAR ]; EncapsulateBytes: PUBLIC PROC [bytes: LONG POINTER, rope: ROPE] ~ TRUSTED { len: NAT ~ rope.Length[]; b: LONG POINTER TO OpaqueByteObject ~ bytes; avo: LONG POINTER TO AttributeValueObject ~ bytes; <> avo.body[0] _ len; FOR i: NAT IN [0..len) DO b.body[i+2] _ rope.InlineFetch[i]; ENDLOOP; IF ( (len MOD 2) = 1 ) THEN b.body[len+2] _ 0C; }; EncapsulateNull: PUBLIC PROC RETURNS [value: AttributeValue] ~ { len: NAT ~ 0; -- wrapped len value _ NEW [AttributeValueObject[len]]; }; <> << AllInterpretedValues: TYPE ~ REF AllInterpretedValuesRep; AllInterpretedValuesRep: TYPE ~ RECORD [ set: PACKED ARRAY Interpreted OF BOOL, checksum: CARDINAL ]; GetInterpretation: PUBLIC PROC [attribute: Attribute, old: AllInterpretedValues _ NIL] RETURNS [new: AllInterpretedValues] ~ { IF old # NIL THEN new _ old ELSE { new _ NEW[AllInterpretedValuesRep]; new.set _ ALL[FALSE] }; IF ( attribute.type IN InterpretedRange ) THEN { color: Interpreted ~ VAL[attribute.type]; new.set[color] _ TRUE; SELECT color FROM checksum => { new.checksum _ DecapsulateCard16[attribute.value]; }; childrenUniquelyNamed => { new.childrenUniquelyNamed _ DecapsulateBoolean[attribute.value] }; createdBy => { new.createdBy _ DecapsulateUser[attribute.value] }; createdOn => { new.createdOn _ DecapsulateCard32[attribute.value] }; fileID => { new.fileID _ DecapsulateFileID[attribute.value] }; isDirectory => { new.isDirectory _ DecapsulateBoolean[attribute.value] }; isTemporary => { new.isTemporary _ DecapsulateBoolean[attribute.value] }; modifiedBy => { new.modifiedBy _ DecapsulateUser[attribute.value] }; modifiedOn => { new.modifiedOn _ DecapsulateCard32[attribute.value] }; name => { new.name _ DecapsulateRope[attribute.value] }; numberOfChildren => { new.numberOfChildren _ DecapsulateCard16[attribute.value] }; ordering => { new.ordering _ DecapsulateOrdering[attribute.value] }; parentID => { new.parentID _ DecapsulateFileID[attribute.value] }; position => { new.position _ DecapsulatePosition[attribute.value] }; readBy => { new.readBy _ DecapsulateUser[attribute.value] }; readOn => { new.readOn _ DecapsulateCard32[attribute.value] }; dataSize => { new.dataSize _ DecapsulateCard32[attribute.value] }; type => { new.type _ DecapsulateCard32[attribute.value] }; version => { new.version _ DecapsulateCard16[attribute.value] }; accessList => { new.accessList _ DecapsulateAccessList[attribute.value] }; defaultAccessList => { new.defaultAccessList _ DecapsulateAccessList[attribute.value] }; pathname => { new.pathname _ DecapsulateRope[attribute.value] }; storedSize => { new.storedSize _ DecapsulateCard32[attribute.value] }; subtreeSize => { new.subtreeSize _ DecapsulateCard32[attribute.value] }; subtreeSizeLimit => { new.subtreeSizeLimit _ DecapsulateCard32[attribute.value] }; ENDCASE => ERROR; }; }; >> }.