-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- IFSFileControl.mesa, HGM, 16-Sep-85 19:35:42 -- Last edited by Gobbel: 27-Jul-81 19:55:35 -- Last edited by Levin: 1-Jul-81 16:43:27 -- Hankins 25-Jul-84 13:42:58 Klamath update (LOOHOLEs) DIRECTORY FileDefs USING [Operations, OperationsRecord], Heap USING [systemZone], IFSFilePrivate USING [ Abandon, Close, CopyString, Destroy, Extend, FinalizeFreeList, FSInstance, FSObject, GetLength, GetTimes, InitializeFreeList, Open, SetCreationTime, SetLength, StartRead, StartWrite, Truncate], Leaf USING [ Answer, AnswerObject, LeafOp, leafSocket, paramsOp, ptLeaf, Request, RequestObject], LogDefs USING [DisplayNumber], PupDefs USING [ GetPupAddress, PupAddress, PupNameTrouble, PupPackageDestroy, PupPackageMake], Sequin USING [ Broken, Buffer, Create, Destroy, Get, GetEmptyBuffer, Handle, Put, ReleaseBuffer], Storage USING [StringLength], String USING [WordsForString], VMDefs USING [Problem, UnableToLogin]; IFSFileControl: MONITOR IMPORTS Heap, IFSFilePrivate, LogDefs, PupDefs, Sequin, Storage, String, VMDefs EXPORTS FileDefs, IFSFilePrivate = BEGIN OPEN IFSFilePrivate; -- Global Variables -- loginCount: CARDINAL; ifsOps: FileDefs.Operations; -- Miscellaneous -- someWordsForFilename: CARDINAL = 15; FilesInUse: ERROR = CODE; InsufficientLogouts: ERROR = CODE; PupBuffersTooSmall: ERROR = CODE; ServerNameMissing: ERROR = CODE; TooManyLogouts: ERROR = CODE; -- Types Exported to FileDefs -- -- Unfortunately, the compiler doesn't support this just yet -- FSInstance: PUBLIC TYPE = IFSFilePrivate.FSInstance; -- Procedures Exported to FileDefs -- InitializeIFS: PUBLIC PROCEDURE RETURNS [ops: FileDefs.Operations] = BEGIN ifsFiles ¬ 0; LogDefs.DisplayNumber["Open IFS Files"L, [short[@ifsFiles]]]; loginCount ¬ 0; InitializeFreeList[]; -- the LOOPHOLEs below get around non-support for multiple implementors of an -- exported type. ifsOps ¬ Heap.systemZone.NEW[ FileDefs.OperationsRecord ¬ [ login: LOOPHOLE[Login], logout: LOOPHOLE[Logout], checkpoint: LOOPHOLE[Checkpoint], abort: LOOPHOLE[Abort], open: LOOPHOLE[Open], close: LOOPHOLE[Close], abandon: LOOPHOLE[Abandon], destroy: LOOPHOLE[Destroy], getLength: LOOPHOLE[GetLength], setLength: LOOPHOLE[SetLength], extend: LOOPHOLE[Extend], truncate: LOOPHOLE[Truncate], startRead: LOOPHOLE[StartRead], startWrite: LOOPHOLE[StartWrite], getTimes: LOOPHOLE[GetTimes], setCreation: LOOPHOLE[SetCreationTime]]]; RETURN[ifsOps] END; FinalizeIFS: PUBLIC PROCEDURE = BEGIN IF loginCount # 0 THEN ERROR InsufficientLogouts; Heap.systemZone.FREE[@ifsOps]; FinalizeFreeList[]; END; -- Variables Exported to IFSFilePrivate -- ifsFiles: PUBLIC CARDINAL; -- Internal Procedures -- Login: PROCEDURE [ server, userName, password, secondaryName, secondaryPassword: LONG STRING ¬ NIL] RETURNS [fs: FSInstance] = BEGIN serverAddr: PupDefs.PupAddress ¬ [net:, host:, socket: Leaf.leafSocket]; TryForConnection: PROCEDURE = BEGIN LeafStringWords: PROCEDURE [s: LONG STRING] RETURNS [CARDINAL] = { RETURN[String.WordsForString[Storage.StringLength[s]] - 1]}; sequin: Sequin.Handle; buffer: Sequin.Buffer ¬ Sequin.GetEmptyBuffer[]; adequate: CARDINAL = 2 * (MAX[SIZE[Leaf.RequestObject], SIZE[Leaf.AnswerObject]] + 1 + LeafStringWords[userName] + LeafStringWords[password] + LeafStringWords[secondaryName] + LeafStringWords[secondaryPassword] + someWordsForFilename); problem: VMDefs.Problem; IF buffer.maxBytes < adequate THEN ERROR PupBuffersTooSmall; sequin ¬ Sequin.Create[dest: serverAddr, pupType: Leaf.ptLeaf]; LOOPHOLE[buffer.data, Leaf.Request]­ ¬ [ Leaf.paramsOp, params[ packetDataBytes: buffer.maxBytes, fileLockTimeout: 2 * 60 / 5, connectionTimeout: 10 * 60 / 5]]; buffer.nBytes ¬ Leaf.paramsOp.length; BEGIN ENABLE Sequin.Broken => {problem ¬ io; GO TO serverDead}; answerOp: Leaf.LeafOp; Sequin.Put[sequin, buffer]; buffer ¬ Sequin.Get[sequin]; answerOp ¬ LOOPHOLE[buffer.data, Leaf.Answer].op; Sequin.ReleaseBuffer[buffer]; IF answerOp.type # params OR answerOp.sense # reply THEN { problem ¬ other; GO TO serverDead}; EXITS serverDead => { Sequin.Destroy[sequin]; ERROR VMDefs.UnableToLogin[problem]}; END; Sequin.Destroy[sequin]; END; NoteLogin: ENTRY PROCEDURE = INLINE {loginCount ¬ loginCount + 1}; IF server = NIL OR server.length = 0 THEN ERROR ServerNameMissing; [] ¬ PupDefs.PupPackageMake[]; PupDefs.GetPupAddress[ @serverAddr, server ! PupDefs.PupNameTrouble => ERROR VMDefs.UnableToLogin[ SELECT code FROM noRoute, noResponse => io, ENDCASE => other]]; TryForConnection[]; fs ¬ Heap.systemZone.NEW[ FSObject ¬ [ primaryName: CopyString[userName], primaryPassword: CopyString[password], secondaryName: CopyString[secondaryName], secondaryPassword: CopyString[secondaryPassword], serverAddr: serverAddr]]; NoteLogin[]; END; Logout: PROCEDURE [fs: FSInstance] = BEGIN NoteLogout: ENTRY PROCEDURE = INLINE {loginCount ¬ loginCount - 1}; IF loginCount = 0 THEN ERROR TooManyLogouts; IF fs.fileList # NIL THEN ERROR FilesInUse; IF fs.primaryName # NIL THEN Heap.systemZone.FREE[@fs.primaryName]; IF fs.primaryPassword # NIL THEN Heap.systemZone.FREE[@fs.primaryPassword]; IF fs.secondaryName # NIL THEN Heap.systemZone.FREE[@fs.secondaryName]; IF fs.secondaryPassword # NIL THEN Heap.systemZone.FREE[@fs.secondaryPassword]; Heap.systemZone.FREE[@fs]; PupDefs.PupPackageDestroy[]; NoteLogout[]; END; Checkpoint: PROCEDURE [fs: FSInstance] = {NULL}; Abort: PROCEDURE [fs: FSInstance] = {NULL}; END.