<> <> <> <> <> <> <> <> <<>> <<>> <<>> <> <<1. When we get around to implementing the resumable signal PossiblyDamaged, the catch of ANY in EstablishTransactionContext will need to be reconsidered.>> <<2. If client can predict what OpenFileID will be returned by Open or Create, he may be able to sneak in by virtue of the temporary access provided for AccessControl operations. Is this worth fixing? If so, how?>> <<3. Similarly, if client can predict what FileID will be generated by Create, he may be able to do an Open that references the leader page before it has been initialized, with undefined results.>> <<4. Should we prevent a client from setting locks inconsistent with the client's access to the file (e.g., write locks on a read-only file, or any locks on a read-protected file)? Permitting this enables a client to tie up an arbitrary file with locks and thereby interfere with other clients' access.>> <<5. Create needs to restrict file types.>> <<>> DIRECTORY OldAlpineFile, AlpineFile, OldAlpineEnvironment; FileActionsImpl: PROGRAM IMPORTS AlpineFile, OldAlpineFile EXPORTS OldAlpineFile = BEGIN OPEN OldAlpineFile; <> Open: PUBLIC PROCEDURE [conversation: Conversation, transID: TransID, universalFile: UniversalFile, access: AccessRights _ readOnly, lock: LockOption _ [intendRead, wait], recoveryOption: RecoveryOption _ log, referencePattern: ReferencePattern _ random] RETURNS [openFileID: OpenFileID, fileID: FileID] = BEGIN Work: PROC = { [openFileID, fileID] _ AlpineFile.Open[conversation, transID, universalFile, access, lock, recoveryOption, referencePattern]; }; DoWork[Work]; END; Create: PUBLIC PROCEDURE [conversation: Conversation, transID: TransID, volumeID: VolOrVolGroupID, owner: OwnerName, initialSize: PageCount, recoveryOption: RecoveryOption _ log, referencePattern: ReferencePattern _ random] RETURNS [openFileID: OpenFileID, universalFile: UniversalFile] = BEGIN Work: PROC = { [openFileID, universalFile] _ AlpineFile.Create[conversation, transID, volumeID, owner, initialSize, recoveryOption, referencePattern]; }; DoWork[Work]; END; Close: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] = BEGIN Work: PROC = { AlpineFile.Close[conversation, openFileID]; }; DoWork[Work]; END; Delete: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] = BEGIN Work: PROC = { AlpineFile.Delete[conversation, openFileID]; }; DoWork[Work]; END; GetUniversalFile: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [universalFile: UniversalFile] = BEGIN Work: PROC = { universalFile _ AlpineFile.GetUniversalFile[conversation, openFileID]; }; DoWork[Work]; END; GetTransID: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [transID: TransID] = BEGIN Work: PROC = { transID _ AlpineFile.GetTransID[conversation, openFileID]; }; DoWork[Work]; END; GetAccessRights: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [access: AccessRights] = BEGIN Work: PROC = { access _ AlpineFile.GetAccessRights[conversation, openFileID]; }; DoWork[Work]; END; GetLockOption: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [lock: LockOption] = BEGIN Work: PROC = { lock _ AlpineFile.GetLockOption[conversation, openFileID]; }; DoWork[Work]; END; SetLockOption: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, lock: LockOption] = BEGIN Work: PROC = { AlpineFile.SetLockOption[conversation, openFileID, lock]; }; DoWork[Work]; END; GetRecoveryOption: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [recoveryOption: RecoveryOption] = BEGIN Work: PROC = { recoveryOption _ AlpineFile.GetRecoveryOption[conversation, openFileID]; }; DoWork[Work]; END; GetReferencePattern: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [referencePattern: ReferencePattern] = BEGIN Work: PROC = { referencePattern _ AlpineFile.GetReferencePattern[conversation, openFileID]; }; DoWork[Work]; END; SetReferencePattern: PUBLIC PROCEDURE [ conversation: Conversation, openFileID: OpenFileID, referencePattern: ReferencePattern] = BEGIN Work: PROC = { AlpineFile.SetReferencePattern[conversation, openFileID, referencePattern]; }; DoWork[Work]; END; ReadProperties: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, desiredProperties: PropertySet _ allProperties, lock: LockOption _ [read, wait]] RETURNS [properties: LIST OF PropertyValuePair] = BEGIN Work: PROC = { properties _ AlpineFile.ReadProperties[conversation, openFileID, desiredProperties, lock]; }; DoWork[Work]; END; WriteProperties: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, properties: LIST OF PropertyValuePair, lock: LockOption _ [update, wait]] = BEGIN Work: PROC = { AlpineFile.WriteProperties[conversation, openFileID, properties, lock]; }; DoWork[Work]; END; UnlockVersion: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] = BEGIN Work: PROC = { AlpineFile.UnlockVersion[conversation, openFileID]; }; DoWork[Work]; END; IncrementVersion: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, increment: LONG CARDINAL] = BEGIN Work: PROC = { AlpineFile.IncrementVersion [conversation, openFileID, increment]; }; DoWork[Work]; END; GetSize: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, lock: LockOption _ [read, wait]] RETURNS [size: PageCount] = BEGIN Work: PROC = { size _ AlpineFile.GetSize [conversation, openFileID, lock]; }; DoWork[Work]; END; SetSize: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, size: PageCount, lock: LockOption _ [update, wait]] = BEGIN Work: PROC = { AlpineFile.SetSize [conversation, openFileID, size, lock]; }; DoWork[Work]; END; UnlockFile: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] = BEGIN Work: PROC = { AlpineFile.UnlockFile [conversation, openFileID]; }; DoWork[Work]; END; DoWork: PROC [work: PROC] RETURNS [] ~ { accessReason: OldAlpineEnvironment.NeededAccess; lockReason: OldAlpineEnvironment.LockFailure; operationReason: OldAlpineEnvironment.OperationFailure; unknownWhat: OldAlpineEnvironment.UnknownType; { ENABLE { AlpineFile.AccessFailed => {accessReason _ missingAccess; GOTO accessFailed}; AlpineFile.LockFailed => { lockReason _ SELECT why FROM conflict, cantConvert => conflict, timeout => timeout, ENDCASE => ERROR; GOTO lockFailed}; AlpineFile.OperationFailed => {operationReason _ why; GOTO operationFailed}; AlpineFile.StaticallyInvalid => {GOTO staticallyInvalid}; AlpineFile.Unknown => {unknownWhat _ what; GOTO unknown}; }; work[]; EXITS accessFailed => ERROR OldAlpineFile.AccessFailed[accessReason]; lockFailed => ERROR OldAlpineFile.LockFailed[lockReason]; operationFailed => ERROR OldAlpineFile.OperationFailed[operationReason]; staticallyInvalid => ERROR OldAlpineFile.StaticallyInvalid; unknown => ERROR OldAlpineFile.Unknown[unknownWhat]; }; }; END. <<>> <<>>