<> <> <> <> <<>> <> <> <> DIRECTORY AccessControl USING[AccessFailed, LockFailed, OperationFailed, StaticallyInvalid, Unknown], AccessControlCache USING[VerifyClient], AccessControlFile USING[LockConflict, LockItem, LockFileOrPageRun], AccessControlMain USING[ChangeSpaceViaOwnerName, CommonChangeOwnerAndHeader, CommonChangeOwner, GetOwnerRecordForReadAndUnlock, PhaseOneSpaceOwnerChanges, ReadAllOwnerProperties], AccessControlMainAux USING[ReadOwnerAccessListFromRecord, ReadOwnerAccListFromRecord], AccessControlPrivate USING[FileDataRec, InternalAccessControlLogicError, OwnerAccListType, PntrAccList, SpecialOwnerForAlpineAdmin, StringRep], AccessControlLight, AccessControlTransMap USING[EnableAlpineWheel, Handle, IsAlpineWheel], AccessControlUtility USING[Compare, CompareCaseMatters, MakeRNameFromStringRep], AlpineEnvironment USING[AccessList, AccessRights, Conversation, LockMode, LockOption, nullRootFile, OpenFileID, OwnerName, OwnerProperty, OwnerPropertySet, OwnerPropertyValuePair, PageCount, Principal, Property, PropertyValuePair, RName, VolumeGroupID, VolumeID], AlpineFile USING[GetUniversalFile, LockFailed, PropertySet, ReadProperties, Unknown], AlpineIdentity USING[myLocalConversation], AlpineInternal USING[TransHandle], AlpineVolume USING[GetEnclosingGroup], ClientMap USING[GetName], Convert USING[RopeFromInt], Rope USING [Cat, ROPE], SkiPatrolHooks USING[TransIDFromTransHandle], SkiPatrolLog USING[notice, OpFailureInfo]; AccessControlLightImpl: CEDAR PROGRAM IMPORTS AC: AccessControl, ACC: AccessControlCache, ACF: AccessControlFile, ACM: AccessControlMain, ACMA: AccessControlMainAux, ACP: AccessControlPrivate, ACU: AccessControlUtility, AF: AlpineFile, AID: AlpineIdentity, AV: AlpineVolume, ClientMap, Convert, Rope, SkiPatrolHooks, SkiPatrolLog, TM: AccessControlTransMap EXPORTS AccessControl, AccessControlLight = BEGIN OPEN AE: AlpineEnvironment, AI: AlpineInternal; <> TheWorld: AE.RName _ "USRegistries^.Internet"; <> AddOwner: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, overCommitQuotaIfNeeded: BOOLEAN, ownerProperties: LIST OF AE.OwnerPropertyValuePair] RETURNS[spaceLeftOnVolumeGroup: AE.PageCount] = TRUSTED BEGIN -- non system-fatal errors: AC.AccessFailed[alpineWheel], AC.LockFailed[timeout], AC.OperationFailed[duplicateOwner, ownerRecordFull, ownerDatabaseFull, totalQuotaExceeded], AC.StaticallyInvalid(badLengthName, badOwnerPropList, reservedOwnerName), AC.Unknown[transID, volumeGroupID]. quota: AE.PageCount; myLockItem: ACF.LockItem; IF NOT TM.IsAlpineWheel[transHandle, conversation] THEN ERROR AC.AccessFailed[alpineWheel]; IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN ERROR AC.StaticallyInvalid; [, quota, ownerProperties] _ ApplyMinsDefaultsAndFilterRequestedWriteProperties[ownerProperties, ownerName, TRUE]; ownerProperties _ CONS[[spaceInUse[0]], ownerProperties]; DO BEGIN RETURN[ACM.CommonChangeOwnerAndHeader[volGroupID, add, transHandle, ownerName, overCommitQuotaIfNeeded, ownerProperties, quota ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]]; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END; RemoveOwner: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName] = TRUSTED BEGIN -- non system-fatal errors: AC.AccessFailed[alpineWheel], AC.LockFailed[timeout], AC.OperationFailed[ownerRecordInUse, spaceInUseByThisOwner], AC.StaticallyInvalid(badLengthName, reservedOwnerName), AC.Unknown[owner, transID, volumeGroupID]. myLockItem: ACF.LockItem; IF NOT TM.IsAlpineWheel[transHandle, conversation] THEN ERROR AC.AccessFailed[alpineWheel]; IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN ERROR AC.StaticallyInvalid; DO BEGIN [] _ ACM.CommonChangeOwnerAndHeader[volGroupID, remove, transHandle, ownerName, TRUE, NIL, 0 ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]; RETURN; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END; WriteOwnerProperties: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, overCommitQuotaIfNeeded: BOOLEAN, ownerProperties: LIST OF AE.OwnerPropertyValuePair] = TRUSTED BEGIN -- non system-fatal errors: AC.AccessFailed[alpineWheel, ownerEntry], AC.LockFailed[timeout], AC.OperationFailed[ownerRecordFull, ownerRecordInUse, regServersUnavailable, totalQuotaExceeded], Ac.StaticallyInvalid(badLengthName, badOwnerPropList, reservedOwnerName), AC.Unknown[owner, transID, volumeGroupID]. needHeader: BOOLEAN; quota: AE.PageCount; myLockItem: ACF.LockItem; IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN ERROR AC.StaticallyInvalid; [needHeader, quota, ownerProperties] _ ApplyMinsDefaultsAndFilterRequestedWriteProperties[ownerProperties, ownerName, FALSE]; IF needHeader THEN BEGIN IF (NOT TM.IsAlpineWheel[transHandle, conversation]) THEN ERROR AC.AccessFailed[alpineWheel]; DO BEGIN [] _ ACM.CommonChangeOwnerAndHeader[volGroupID, writeProps, transHandle, ownerName, overCommitQuotaIfNeeded, ownerProperties, quota ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]; RETURN; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END ELSE BEGIN <> IF (NOT TM.IsAlpineWheel[transHandle, conversation]) THEN FOR ownerProperty: LIST OF AE.OwnerPropertyValuePair _ ownerProperties, ownerProperty.rest UNTIL ownerProperty = NIL DO SELECT ownerProperty.first.property FROM createAccessList => IF (NOT CheckClientInOwnerAccessLists[conversation, transHandle, volGroupID, ownerName, [create: FALSE, modify: TRUE]][modify]) THEN ERROR AC.AccessFailed[ownerEntry]; rootFile => IF (NOT CheckClientInOwnerAccessLists[conversation, transHandle, volGroupID, ownerName, [create: TRUE, modify: FALSE]][create]) THEN ERROR AC.AccessFailed[ownerEntry]; modifyAccessList => ERROR AC.AccessFailed[ownerEntry]; ENDCASE => ERROR ACP.InternalAccessControlLogicError; ENDLOOP; DO BEGIN ACM.CommonChangeOwner[volGroupID, transHandle, ownerName, ownerProperties ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]; RETURN; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END; END; ReadOwnerProperties: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, desiredOwnerProperties: AE.OwnerPropertySet] RETURNS [ownerProperties: LIST OF AE.OwnerPropertyValuePair] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.StaticallyInvalid(badLengthName), AC.Unknown[owner, transID, volumeGroupID]. myLockItem: ACF.LockItem; DO BEGIN RETURN[ACM.ReadAllOwnerProperties[volGroupID, transHandle, ownerName, desiredOwnerProperties ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]]; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END; <> ChangeSpaceViaOwner: PUBLIC PROCEDURE[transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, nPages: AE.PageCount] RETURNS [okay: BOOLEAN] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.StaticallyInvalid(badLengthName), AC.Unknown[owner, transID, volumeGroupID]. myLockItem: ACF.LockItem; IF ((nPages = 0) OR (ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin])) THEN RETURN[TRUE]; DO BEGIN RETURN[ACM.ChangeSpaceViaOwnerName[volGroupID, transHandle, ownerName, nPages ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]]; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END; <> ChangeSpaceForOwner: PUBLIC PROCEDURE [conversation: AE.Conversation, transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, nPages: AE.PageCount] = BEGIN -- non system-fatal errors: AC.AccessFailed[alpineWheel], AC.LockFailed[timeout], AC.OperationFailed[quotaExceeded], AC.StaticallyInvalid(badLengthName), AC.Unknown[owner, transID, volumeGroupID]. IF NOT TM.IsAlpineWheel[transHandle, conversation] THEN ERROR AC.AccessFailed[alpineWheel]; IF NOT ChangeSpaceViaOwner[transHandle, volGroupID, ownerName, nPages] THEN { logProc: PROC [SkiPatrolLog.OpFailureInfo]; IF (logProc _ SkiPatrolLog.notice.operationFailed) # NIL THEN logProc[[ what: quotaExceeded, where: "AccessControlLightImpl.ChangeSpaceForOwner", transID: SkiPatrolHooks.TransIDFromTransHandle[transHandle], message: Rope.Cat["Quota exceeded for ", ownerName, "; nPages = ", Convert.RopeFromInt[nPages]] ]]; ERROR AC.OperationFailed[quotaExceeded]; }; END; InconsistencyBetweenFilePropAndOwnerDataBase: ERROR = CODE; ChangeSpaceViaOpenFileID: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, openFileID: AE.OpenFileID, nPages: AE.PageCount] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.Unknown[openFileID, transID, volumeGroupID]. ownerName: AE.OwnerName _ ReadOwnerName[conversation, openFileID]; IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN RETURN[TRUE]; RETURN[ChangeSpaceViaOwner[transHandle, GetVolGroupIDFromOpenFileID[conversation, openFileID], ownerName, nPages ! AC.StaticallyInvalid => GOTO horrible; AC.Unknown => IF why = owner THEN GOTO horrible]]; EXITS horrible => ERROR InconsistencyBetweenFilePropAndOwnerDataBase; END; <> PermissionToCreateFilesForThisOwner: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.OperationFailed[regServersUnavailable], AC.StaticallyInvalid(badLengthName, reservedOwnerName), AC.Unknown[owner, transID, volumeGroupID]. IF conversation = AID.myLocalConversation THEN RETURN[TRUE]; IF TM.IsAlpineWheel[transHandle, conversation] THEN BEGIN IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN ERROR AC.StaticallyInvalid ELSE RETURN[TRUE]; END; RETURN[CheckClientInOwnerAccessLists[conversation, transHandle, volGroupID, ownerName, [create: TRUE, modify: FALSE]][create]]; END; <> PermissionToModifyFileAccessList: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, openFileID: AE.OpenFileID] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.OperationFailed[regServersUnavailable], AC.StaticallyInvalid(badLengthName, reservedOwnerName), AC.Unknown[openFileID, transID, volumeID, volumeGroupID]. volGroupID: AE.VolumeGroupID; ownerName: AE.OwnerName _ ReadOwnerName[conversation, openFileID]; IF TM.IsAlpineWheel[transHandle, conversation] THEN BEGIN IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN ERROR AC.StaticallyInvalid ELSE RETURN[TRUE]; END; volGroupID _ GetVolGroupIDFromOpenFileID[conversation, openFileID]; RETURN[CheckClientInOwnerAccessLists[conversation, transHandle, volGroupID, ownerName, [create: TRUE, modify: FALSE]][create]]; END; CheckClientInOwnerAccessLists: PROCEDURE[conversation: AE.Conversation, transHandle: TM.Handle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, reqLists: ARRAY ACP.OwnerAccListType OF BOOLEAN] RETURNS [inList: ARRAY ACP.OwnerAccListType OF BOOLEAN] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.OperationFailed[regServersUnavailable], AC.StaticallyInvalid(badLengthName), AC.Unknown[owner, transID, volumeGroupID]. fileDataRec: ACP.FileDataRec; myLockItem: ACF.LockItem; DO BEGIN ACM.GetOwnerRecordForReadAndUnlock[volGroupID, transHandle, ownerName, @fileDataRec ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]; EXIT; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; FOR listType: ACP.OwnerAccListType IN ACP.OwnerAccListType DO inList[listType] _ (IF reqLists[listType] THEN IsClientInOwnerAccList[conversation, ACMA.ReadOwnerAccListFromRecord[@fileDataRec, listType], ownerName] ELSE FALSE); ENDLOOP; END; <> PermissionToAccessFile: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, openFileID: AE.OpenFileID, requestedAccess: AE.AccessRights, lockOption: AE.LockOption _ [read,wait]] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.OperationFailed[regServersUnavailable], AC.StaticallyInvalid(reservedOwnerName), AC.Unknown[openFileID, transID]. IF conversation = AID.myLocalConversation THEN RETURN[TRUE]; IF TM.IsAlpineWheel[transHandle, conversation] THEN BEGIN IF ACU.Compare[ReadOwnerName[conversation, openFileID, lockOption], ACP.SpecialOwnerForAlpineAdmin] THEN ERROR AC.StaticallyInvalid ELSE RETURN[TRUE]; END; SELECT requestedAccess FROM readWrite => RETURN[IsClientInFileAccessList[conversation, openFileID, ReadFileAccessList[conversation, openFileID, readWrite, lockOption], lockOption]]; readOnly => okay _ IsClientInFileAccessList[conversation, openFileID, ReadFileAccessList[conversation, openFileID, readOnly, lockOption], lockOption] OR IsClientInFileAccessList[conversation, openFileID, ReadFileAccessList[conversation, openFileID, readWrite, lockOption], lockOption]; ENDCASE => ERROR; END; <> GetDefaultForFileAccessList: PUBLIC PROCEDURE[transHandle: AI.TransHandle, volGroupID: AE.VolumeGroupID, ownerName: AE.OwnerName, accessListType: AE.AccessRights] RETURNS[accessList: AlpineEnvironment.AccessList] = BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC..StaticallyInvalid(badLengthName), AC.Unknown[owner, transID, volumeGroupID]. accessList _ NIL; IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN RETURN; SELECT accessListType FROM readWrite => TRUSTED BEGIN fileDataRec: ACP.FileDataRec; myLockItem: ACF.LockItem; DO BEGIN ACM.GetOwnerRecordForReadAndUnlock[volGroupID, transHandle, ownerName, @fileDataRec ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]; EXIT; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; accessList _ ACMA.ReadOwnerAccessListFromRecord[@fileDataRec, create, ownerName]; END; ENDCASE => accessList _ CONS["world", accessList]; END; <> <> ApplyMinsDefaultsAndFilterRequestedWriteProperties: PUBLIC PROCEDURE[ownerProperties: LIST OF AE.OwnerPropertyValuePair, ownerName: AE.OwnerName, supplyDefaults: BOOLEAN] RETURNS[quotaPresent: BOOLEAN, quota: AE.PageCount, newOwnerProperties: LIST OF AE.OwnerPropertyValuePair] = TRUSTED BEGIN -- non system-fatal errors: AC.StaticallyInvalid(badOwnerPropList). ownerPropertySet: AE.OwnerPropertySet _ ALL[FALSE]; quotaPresent _ FALSE; quota _ 0; newOwnerProperties _ NIL; FOR ownerProperty: LIST OF AE.OwnerPropertyValuePair _ ownerProperties, ownerProperty.rest UNTIL ownerProperty = NIL DO IF ownerPropertySet[ownerProperty.first.property] THEN ERROR AC.StaticallyInvalid; ownerPropertySet[ownerProperty.first.property] _ TRUE; WITH prop: ownerProperty.first SELECT FROM createAccessList => newOwnerProperties _ CONS[[createAccessList[ApplyMinToOwnerAccessList[prop.createAccessList, create, ownerName]]], newOwnerProperties]; modifyAccessList => newOwnerProperties _ CONS[[modifyAccessList[ApplyMinToOwnerAccessList[prop.modifyAccessList, modify, ownerName]]], newOwnerProperties]; rootFile => newOwnerProperties _ CONS[[rootFile[prop.rootFile]], newOwnerProperties]; quota => BEGIN quotaPresent _ TRUE; newOwnerProperties _ CONS[[quota[prop.quota]], newOwnerProperties]; END; ENDCASE => ERROR AC.StaticallyInvalid; ENDLOOP; IF supplyDefaults THEN BEGIN IF NOT ownerPropertySet[createAccessList] THEN newOwnerProperties _ CONS[[createAccessList[GetDefaultForOwnerAccessList[create, ownerName]]], newOwnerProperties]; IF NOT ownerPropertySet[modifyAccessList] THEN newOwnerProperties _ CONS[[modifyAccessList[GetDefaultForOwnerAccessList[modify, ownerName]]], newOwnerProperties]; IF NOT ownerPropertySet[quota] THEN BEGIN newOwnerProperties _ CONS[[quota[0]], newOwnerProperties]; quotaPresent _ TRUE; END; IF NOT ownerPropertySet[rootFile] THEN newOwnerProperties _ CONS[[rootFile[AE.nullRootFile]], newOwnerProperties]; END; END; <> ApplyMinToOwnerAccessList: PROCEDURE [accessList: AE.AccessList, accListType: ACP.OwnerAccListType, ownerName: AE.OwnerName] RETURNS[newAccessList: AE.AccessList] = BEGIN -- non system-fatal errors: none. ownerSeen: BOOLEAN _ FALSE; newAccessList _ NIL; FOR list: AE.AccessList _ accessList, list.rest UNTIL list = NIL DO SELECT TRUE FROM ACU.Compare[list.first, "world"], ACU.CompareCaseMatters[list.first, "*"] => NULL; ACU.Compare[list.first, "owner"], ACU.Compare[list.first, ownerName] => NULL; ENDCASE => newAccessList _ CONS[list.first, newAccessList]; ENDLOOP; newAccessList _ CONS["Owner", newAccessList]; END; GetDefaultForOwnerAccessList: PROCEDURE [accListType: ACP.OwnerAccListType, ownerName: AE.OwnerName] RETURNS[accessList: AE.AccessList] = BEGIN -- non system-fatal errors: none. IF ACU.Compare[ownerName, ACP.SpecialOwnerForAlpineAdmin] THEN RETURN[NIL] ELSE RETURN[LIST["Owner"]]; END; <> IsClientInOwnerAccList: PROCEDURE[conversation: AE.Conversation, pntrAccList: ACP.PntrAccList, ownerName: AE.OwnerName] RETURNS [okay: BOOLEAN] = TRUSTED BEGIN -- non system-fatal errors: AC.OperationFailed[regServersUnavailable]. clientName: AE.Principal; accessList: AE.AccessList _ NIL; pntrStringRep: LONG POINTER TO ACP.StringRep _ @pntrAccList.principals; TRUSTED { clientName _ ClientMap.GetName[conversation] }; IF ((pntrAccList.owner OR pntrAccList.world ) AND (IsClientInListOfVanillaNames[clientName, LIST[ownerName]])) THEN RETURN[TRUE]; IF pntrAccList.world THEN accessList _ CONS[TheWorld, accessList]; FOR accListCount: CARDINAL IN [0..pntrAccList.count) DO name: AE.RName; size: CARDINAL; [name, size] _ ACU.MakeRNameFromStringRep[pntrStringRep]; accessList _ CONS[name, accessList]; pntrStringRep _ pntrStringRep + size; ENDLOOP; RETURN[IsClientInListOfVanillaNames[clientName, accessList]]; END; <> IsClientInFileAccessList: PROCEDURE[conversation: AE.Conversation, openFileID: AE.OpenFileID, accessList: AE.AccessList, lockOption: AE.LockOption] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.OperationFailed[regServersUnavailable], AC.Unknown[openFileID, transID]. newAccessList: AE.AccessList _ NIL; worldSeen: BOOLEAN _ FALSE; ownerName: AE.Principal = ReadOwnerName[conversation, openFileID, lockOption]; clientName: AE.Principal; TRUSTED { clientName _ ClientMap.GetName[conversation] }; FOR list: AE.AccessList _ accessList, list.rest UNTIL list = NIL DO SELECT TRUE FROM ACU.Compare[list.first, "world"] OR ACU.CompareCaseMatters[list.first, "*"] => { IF ACU.Compare[ownerName, clientName] THEN RETURN[TRUE]; worldSeen _ TRUE; }; ACU.Compare[list.first, "owner"] => IF ACU.Compare[ownerName, clientName] THEN RETURN[TRUE]; ENDCASE => newAccessList _ CONS[list.first, newAccessList]; ENDLOOP; IF worldSeen THEN newAccessList _ CONS[TheWorld, newAccessList]; okay _ IsClientInListOfVanillaNames[clientName, newAccessList]; END; <> IsClientInListOfVanillaNames: PROCEDURE[clientName: AE.Principal, accessList: AE.AccessList] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.OperationFailed[regServersUnavailable]. FOR list: AE.AccessList _ accessList, list.rest -- check for direct match. UNTIL list = NIL DO IF ACU.Compare[list.first, clientName] THEN RETURN[TRUE]; ENDLOOP; RETURN[ACC.VerifyClient[clientName, accessList]]; -- check in group. END; <> GetVolGroupIDFromOpenFileID: PROCEDURE[conversation: AE.Conversation, openFileID: AE.OpenFileID] RETURNS[volGroupID: AE.VolumeGroupID] = TRUSTED BEGIN -- non system-fatal errors: AC.Unknown[openFileID, transID]. ENABLE AF.Unknown => SELECT what FROM openFileID => GOTO unkOpenFileID; transID => GOTO untTransID; ENDCASE => NULL; RETURN[AV.GetEnclosingGroup[AID.myLocalConversation, , AF.GetUniversalFile[ conversation, openFileID].volumeID]]; EXITS unkOpenFileID => ERROR AC.Unknown[openFileID]; untTransID => ERROR AC.Unknown[transID]; END; ReadOwnerName: PROCEDURE[conversation: AE.Conversation, openFileID: AE.OpenFileID, lockOption: AE.LockOption _ [read,wait]] RETURNS[ownerName: AE.OwnerName] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.Unknown[openFileID, transID]. WITH pVP: ReadFileProperty[conversation, openFileID, owner, lockOption].first SELECT FROM owner => ownerName _ pVP.owner; ENDCASE => ERROR; END; ReadFileAccessList: PROCEDURE[conversation: AE.Conversation, openFileID: AE.OpenFileID, accessListType: AE.AccessRights, lockOption: AE.LockOption] RETURNS[fileAccessList: AE.AccessList] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.Unknown[openFileID, transID]. desiredProperty: AE.Property _ (SELECT accessListType FROM readOnly => readAccess, ENDCASE => modifyAccess); WITH pVP: ReadFileProperty[conversation, openFileID, desiredProperty, lockOption].first SELECT FROM readAccess => BEGIN IF desiredProperty # readAccess THEN ERROR; fileAccessList _ pVP.readAccess; END; modifyAccess => BEGIN IF desiredProperty # modifyAccess THEN ERROR; fileAccessList _ pVP.modifyAccess; END; ENDCASE => ERROR; END; ReadFileProperty: PROCEDURE[conversation: AE.Conversation, openFileID: AE.OpenFileID, desiredProperty: AE.Property, lockOption: AE.LockOption] RETURNS[list: LIST OF AE.PropertyValuePair] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.Unknown[openFileID, transID]. propSet: AF.PropertySet _ ALL[FALSE]; propSet[desiredProperty] _ TRUE; RETURN[AF.ReadProperties[conversation, openFileID, propSet, [read, lockOption.ifConflict] ! AF.Unknown => SELECT what FROM openFileID => GOTO unkOpenFile; transID => GOTO unkTransID; ENDCASE => NULL; AF.LockFailed => SELECT why FROM conflict => GOTO conflict; timeout => GOTO deadlock; ENDCASE => NULL]]; EXITS <> conflict => ERROR AC.LockFailed[conflict]; deadlock => ERROR AC.LockFailed[timeout]; unkOpenFile => ERROR AC.Unknown[openFileID]; unkTransID => ERROR AC.Unknown[transID]; END; AlpineWheelsOwnerName: AE.OwnerName _ NIL; AssertAlpineWheel: PUBLIC PROCEDURE[conversation: AE.Conversation, transHandle: AI.TransHandle, assert: BOOLEAN] RETURNS [okay: BOOLEAN] = BEGIN -- non system-fatal errors: AC.OperationFailed[regServersUnavailable]. IF assert THEN BEGIN principal: AE.Principal; TRUSTED BEGIN principal _ ClientMap.GetName[conversation]; END; IF NOT ACC.VerifyClient[principal, LIST[AlpineWheelsOwnerName]] THEN RETURN[FALSE]; END; TM.EnableAlpineWheel[transHandle, conversation, assert]; RETURN[TRUE]; END; <> PhaseOneSpaceAndOwnerChanges: PUBLIC PROCEDURE[transHandle: TM.Handle] = TRUSTED BEGIN -- non system-fatal errors: AC.LockFailed[timeout], AC.Unknown[transID]. myLockItem: ACF.LockItem; DO BEGIN ACM.PhaseOneSpaceOwnerChanges[transHandle ! ACF.LockConflict => BEGIN myLockItem.mode _ lockItem.mode; WITH l: lockItem SELECT FROM file => myLockItem.whatToLock _ file[l.transID, l.universalFile, l.refPattern]; pageRun => myLockItem.whatToLock _ pageRun[l.openFileID, l.pageRun]; ENDCASE; GOTO lockConflict; END]; RETURN; EXITS lockConflict => ACF.LockFileOrPageRun[myLockItem]; -- may error AC.OperationFailed[lockTimeout]. END; ENDLOOP; END; SetAccessControlLightInitialized: PUBLIC PROCEDURE[alpineWheels: AE.OwnerName] = BEGIN -- non system-fatal errors: none. AlpineWheelsOwnerName _ alpineWheels; END; END. Edit Log Initial: Kolling: January 11, 1983 5:52 pm: upper level module for "light" operations. Edited on July 24, 1984 2:55:28 pm PDT, by Kupfer <> <> <> <> <> <<>>