-- AccessControlMainAuxImpl.mesa
-- Last edited by
-- Kolling on May 17, 1983 3:13 pm
-- MBrown on January 30, 1984 11:32:46 am PST


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];


AccessControlMainAuxImpl: PROGRAM
IMPORTS AC: AccessControl, ACP: AccessControlPrivate, ACU: AccessControlUtility, PrincOpsUtils
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 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.OwnerPropertyRepReadOwnerPropFromRecord[
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.