AccessControlMainAuxImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by
Kolling on May 17, 1983 3:13 pm
MBrown on January 30, 1984 11:32:46 am PST
Last Edited by: Kupfer, August 6, 1984 2:38:10 pm PDT
DIRECTORY
AccessControl
USING[OperationFailed],
AccessControlMain,
AccessControlMainAux,
AccessControlPrivate
USING[AccList, FileDataRecOffset, InternalAccessControlLogicError, MinSizeAccListRep,
OffsetData, OwnerAccListType, OwnerPropertyPickleMap, OwnerPropertyRep,
PickledOwnerProperty, PntrAccList, PntrDataRec, StringRep],
AccessControlUtility
USING[Compare, CompareCaseMatters, MakeRNameFromStringRep,
MakeStringRepFromRName],
AlpineEnvironment
USING[AccessList, OwnerName, nullRootFile, OwnerProperty,
OwnerPropertyValuePair, PageCount, UniversalFile, wordsPerPage],
PrincOpsUtils
USING[LongCopy],
Rope
USING[Concat],
SkiPatrolLog
USING[notice, OpFailureInfo];
AccessControlMainAuxImpl: PROGRAM
IMPORTS AC: AccessControl, ACP: AccessControlPrivate, ACU: AccessControlUtility, PrincOpsUtils, Rope, SkiPatrolLog
EXPORTS AccessControlMainAux =
BEGIN OPEN AE: AlpineEnvironment;
procedures that transfer between the owner record and properties:
when an owner record is added, the two access lists, the quota, and the spaceinuse properties are specified; the rootfile property is only specified if the client has specified it. Consequently all subsequent writes can expect properties other than the rootfile property to exist.
InitializeOwnerRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec] =
TRUSTED
BEGIN -- non system-fatal errors: none.
pntrFileDataRec.state ← empty;
pntrFileDataRec.ownerName ← [length: 0, text: ];
pntrFileDataRec.dataStart ← ACP.OffsetData;
pntrFileDataRec.dataEnd ← ACP.OffsetData;
END;
assumes it is okay for the properties to not already exist in the record.
WriteOwnerPropsToRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec,
ownerProperties: LIST OF AE.OwnerPropertyValuePair, ownerName: AE.OwnerName] =
CHECKED
BEGIN -- non system-fatal errors: AC.OperationFailed[ownerRecordFull], AC.StaticallyInvalid(badLengthName).
FOR ownerProperty: LIST OF AE.OwnerPropertyValuePair ← ownerProperties, ownerProperty.rest
UNTIL ownerProperty = NIL
DO
RemoveOwnerPropFromRecord[pntrFileDataRec,
ACP.OwnerPropertyPickleMap[ownerProperty.first.property]
! NotFound => CONTINUE];
ENDLOOP;
FOR ownerProperty: LIST OF AE.OwnerPropertyValuePair ← ownerProperties,
ownerProperty.rest
UNTIL ownerProperty = NIL
DO
WriteOwnerPropToRecord[pntrFileDataRec, ownerProperty.first, ownerName];
ENDLOOP;
END;
signals NotFound if owner prop not found.
RemoveOwnerPropFromRecord: SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec,
pickledOwnerProp: ACP.PickledOwnerProperty] = TRUSTED
BEGIN -- non system-fatal errors: none.
ownerProp: LONG POINTER TO ACP.OwnerPropertyRep ← LOOPHOLE[pntrFileDataRec +
FindOffsetOfOwnerProp[pntrFileDataRec, pickledOwnerProp]];
size: CARDINAL ← ownerProp.size;
PrincOpsUtils.LongCopy[to: ownerProp, from: ownerProp + size, nwords: pntrFileDataRec.dataEnd -
(pntrFileDataRec.dataStart + size)];
pntrFileDataRec.dataEnd ← pntrFileDataRec.dataEnd - size;
END;
assumes property is not already in record.
WriteOwnerPropToRecord: SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec,
ownerProperty: AE.OwnerPropertyValuePair, ownerName: AE.OwnerName] = TRUSTED
BEGIN -- non system-fatal errors: AC.OperationFailed[ownerRecordFull], AC.StaticallyInvalid(badLengthName).
pickledOwnerProperty: ACP.PickledOwnerProperty ←
ACP.OwnerPropertyPickleMap[ownerProperty.property];
ownerProp: LONG POINTER TO ACP.OwnerPropertyRep ← LOOPHOLE[pntrFileDataRec +
pntrFileDataRec.dataEnd];
roomAvailable: CARDINALAE.wordsPerPage - pntrFileDataRec.dataEnd;
ownerPropSize: CARDINALSIZE[ACP.OwnerPropertyRep];
IF roomAvailable < ownerPropSize THEN {
logProc: PROC [SkiPatrolLog.OpFailureInfo];
IF (logProc ← SkiPatrolLog.notice.operationFailed) # NIL THEN
logProc[[
what: ownerRecordFull,
where: "AccessControlMainAuxImpl.WriteOwnerPropToRecord",
message: Rope.Concat["Owner = ", ownerName]
]];
ERROR AC.OperationFailed[ownerRecordFull];
};
ownerProp.ownerProperty ← pickledOwnerProperty;
WITH ownerProperty
SELECT FROM
createAccessList => WITH prop: ownerProp SELECT createAccList FROM createAccList
=> ownerPropSize ← CondenseOwnerAccessList[createAccessList,
ownerName, @prop.createAccList, roomAvailable]; ENDCASE;
modifyAccessList => WITH prop: ownerProp SELECT modifyAccList FROM
modifyAccList => ownerPropSize ←
CondenseOwnerAccessList[modifyAccessList,
ownerName, @prop.modifyAccList, roomAvailable]; ENDCASE;
quota => WITH prop: ownerProp SELECT quota FROM quota => prop.quota ← quota; ENDCASE;
rootFile => WITH prop: ownerProp SELECT rootFile FROM rootFile => prop.rootFile ←
rootFile; ENDCASE;
spaceInUse => WITH prop: ownerProp SELECT spaceInUse FROM spaceInUse =>
prop.spaceInUse ← spaceInUse; ENDCASE;
ENDCASE;
ownerProp.size ← ownerPropSize;
pntrFileDataRec.dataEnd ← pntrFileDataRec.dataEnd + ownerPropSize;
END;
OverWriteOwnerSpaceInUseToRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec:
ACP.PntrDataRec, spaceInUse: AE.PageCount] = TRUSTED
BEGIN -- non system-fatal errors: none.
pntrOwnerProp: LONG POINTER TO ACP.OwnerPropertyRep ←
ReadOwnerPropFromRecord[pntrFileDataRec, spaceInUse];
WITH prop: pntrOwnerProp
SELECT spaceInUse FROM
spaceInUse => prop.spaceInUse ← spaceInUse;
ENDCASE;
END;
signals NotFound if owner prop not found.
ReadOwnerPropFromRecord: SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec,
pickledOwnerProperty: ACP.PickledOwnerProperty] RETURNS[pntrOwnerProp:
LONG POINTER TO ACP.OwnerPropertyRep] = TRUSTED
BEGIN -- non system-fatal errors: none.
RETURN[LOOPHOLE[pntrFileDataRec + FindOffsetOfOwnerProp[pntrFileDataRec,
pickledOwnerProperty], LONG POINTER TO ACP.OwnerPropertyRep]];
END;
ReadOwnerQuotaFromRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec]
RETURNS[quota: AE.PageCount] = TRUSTED
BEGIN -- non system-fatal errors: none.
WITH prop: ReadOwnerPropFromRecord[pntrFileDataRec, quota]^
SELECT quota FROM
quota => quota ← prop.quota;
ENDCASE => ERROR ACP.InternalAccessControlLogicError;
END;
returns nullRootFile if no rootFile property in the record.
ReadOwnerRootFileFromRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec]
RETURNS[rootFile: AE.UniversalFile] = TRUSTED
BEGIN -- non system-fatal errors: none.
pntrOwnerProp: LONG POINTER TO ACP.OwnerPropertyRep ← ReadOwnerPropFromRecord[
pntrFileDataRec, rootFile
! NotFound => GOTO notFound];
WITH prop: pntrOwnerProp^
SELECT rootFile FROM
rootFile => rootFile ← prop.rootFile;
ENDCASE => ERROR ACP.InternalAccessControlLogicError;
EXITS notFound =>RETURN[AE.nullRootFile];
END;
ReadOwnerSpaceInUseFromRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec:
ACP.PntrDataRec] RETURNS[spaceInUse: AE.PageCount] = TRUSTED
BEGIN -- non system-fatal errors: none.
WITH prop: ReadOwnerPropFromRecord[pntrFileDataRec, spaceInUse]^
SELECT spaceInUse FROM
spaceInUse => spaceInUse ← prop.spaceInUse;
ENDCASE => ERROR ACP.InternalAccessControlLogicError;
END;
ReadOwnerAccListFromRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec,
accListType: ACP.OwnerAccListType] RETURNS[pntrAccList: ACP.PntrAccList]
= TRUSTED
BEGIN -- non system-fatal errors: none.
pntrOwnerProp: LONG POINTER TO ACP.OwnerPropertyRep ←
ReadOwnerPropFromRecord[pntrFileDataRec, (IF accListType = create THEN
createAccList ELSE modifyAccList)];
RETURN[LOOPHOLE[@pntrOwnerProp.value, ACP.PntrAccList]];
END;
ReadOwnerAccessListFromRecord: PUBLIC SAFE PROCEDURE[pntrFileDataRec:
ACP.PntrDataRec, accListType: ACP.OwnerAccListType, ownerName: AE.OwnerName]
RETURNS[accessList: AE.AccessList] = CHECKED
BEGIN -- non system-fatal errors: none.
RETURN[ExpandOwnerAccList[ReadOwnerAccListFromRecord[pntrFileDataRec,
accListType], ownerName]];
END;
ExpandOwnerAccList: SAFE PROCEDURE[pntrAccList: ACP.PntrAccList, ownerName:
AE.OwnerName] RETURNS[accessList: AE.AccessList] = TRUSTED
BEGIN -- non system-fatal errors: none.
ownerSeen: BOOLEANFALSE;
pntrStringRep: LONG POINTER TO ACP.StringRep ← @pntrAccList.principals;
accessList ← NIL;
FOR accListCount: CARDINAL IN [0..pntrAccList.count)
DO
name: AE.OwnerName;
size: CARDINAL;
[name, size] ← ACU.MakeRNameFromStringRep[pntrStringRep];
pntrStringRep ← pntrStringRep + size;
IF ACU.Compare[name, ownerName]
THEN ownerSeen ← TRUE
ELSE accessList ← CONS[name, accessList];
ENDLOOP;
IF (ownerSeen OR pntrAccList.owner)
THEN accessList ← CONS["owner", accessList];
IF pntrAccList.world THEN accessList ← CONS["world", accessList];
END;
signals NotFound if owner prop not found.
NotFound: ERROR = CODE;
FindOffsetOfOwnerProp: SAFE PROCEDURE[pntrFileDataRec: ACP.PntrDataRec,
pickledOwnerProp: ACP.PickledOwnerProperty] RETURNS[offsetToOwnerProp:
ACP.FileDataRecOffset] = TRUSTED
BEGIN -- non system-fatal errors: none.
offsetToOwnerProp ← pntrFileDataRec.dataStart;
WHILE offsetToOwnerProp < pntrFileDataRec.dataEnd
DO
pntrOwnerProp: LONG POINTER TO ACP.OwnerPropertyRep ←
LOOPHOLE[pntrFileDataRec + offsetToOwnerProp];
IF pntrOwnerProp.ownerProperty = pickledOwnerProp THEN EXIT;
offsetToOwnerProp ← offsetToOwnerProp + pntrOwnerProp.size;
REPEAT FINISHED => ERROR NotFound;
ENDLOOP;
END;
just condenses to the short form, does not apply minimums. catches the owner name, but does not attempt to eliminate any other duplicates.
CondenseOwnerAccessList: SAFE PROCEDURE[accessList: AE.AccessList, ownerName:
AE.OwnerName, pntrAccList: ACP.PntrAccList, roomAvailable: CARDINAL]
RETURNS[totalSizeOfOwnerPropertyRep: CARDINAL] = TRUSTED
BEGIN -- non system-fatal errors: AC.OperationFailed[ownerRecordFull], AC.StaticallyInvalid(badLengthName).
pntrStringRep: LONG POINTER TO ACP.StringRep ← @pntrAccList.principals;
totalSizeOfOwnerPropertyRep ← roomAvailable;
roomAvailable ← roomAvailable - ACP.MinSizeAccListRep; -- room left for StringReps.
pntrAccList^ ← [world: FALSE, owner: FALSE, gap: 0, count: 0, principals: ];
IF accessList # NIL
THEN BEGIN
tempList: AE.AccessList;
FOR tempList ← accessList, tempList.rest UNTIL tempList = NIL
DO
SELECT TRUE FROM
ACU.CompareCaseMatters[tempList.first, "*"],
ACU.Compare[tempList.first, "world"] => pntrAccList.world ← TRUE;
ACU.Compare[tempList.first, ownerName],
ACU.Compare[tempList.first, "owner"] => pntrAccList.owner ← TRUE;
ENDCASE => BEGIN
sizeOfStringRep: CARDINALACU.MakeStringRepFromRName[tempList.first,
pntrStringRep, roomAvailable];
pntrStringRep ← pntrStringRep + sizeOfStringRep;
roomAvailable ← roomAvailable - sizeOfStringRep;
pntrAccList.count ← pntrAccList.count+ 1;
END;
ENDLOOP;
END;
totalSizeOfOwnerPropertyRep ← totalSizeOfOwnerPropertyRep - roomAvailable;
END;
END.
Edit Log
Initial: Kolling: January 14, 1983 1:14 pm: things moved here because AccessControlMainImpl was too big.
Edited on July 17, 1984 11:42:40 am PDT, by Kupfer
Add SkiPatrolLog probe.
changes to: WriteOwnerPropToRecord
Edited on August 6, 1984 2:37:29 pm PDT, by Kupfer
Remove the possible race condition in SkiPatrolLog probes by assigning the PROC to a temporary variable.
changes to: WriteOwnerPropToRecord