<> <> <> <> <> <> <> <> <> DIRECTORY BasicTime USING [GMT, Now, nullGMT, Pack, Unpack, Unpacked], FS USING [Error, ErrorGroup, FileType, tUnspecified], FSBackdoor USING [ErrorCode, ProduceError, Version], FSName USING [BangStarFile, BangVersionFile, VersionFromRope], FSRemoteFile USING [], FSRemoteFileBackdoor USING [CloseProc, DeleteProc, DoProc, EnumerateForInfoProc, EnumerateForNamesProc, ErrorNotImplemented, GetInfoProc, GetServerProc, OpenProc, Register, RenameProc, RetrieveProc, RWProc, ServerHandle, ServerObject, ServerProcs, ServerProcsObject, StoreProc, SweepProc, ValidateProc], FSReport USING [UnknownFile], GVBasics USING [Connect], GVNames USING [ConnectInfo, GetConnect], IO USING [STREAM], Process USING [CheckForAbort, Detach, EnableAborts], Rope USING [Cat, Concat, Equal, Fetch, Find, FindBackward, Length, Match, ROPE], RuntimeError USING [UNCAUGHT], SafeStorage USING [EnableFinalization, EstablishFinalization, FinalizationQueue, FQEmpty, FQNext, NewFQ], STP USING [Close, ConfirmProcType, Continue, Create, Delete, DesiredProperties, Enumerate, Error, ErrorCode, FileInfo, GetFileInfo, Handle, IsOpen, Login, NoteFileProcType, Open, Rename, Retrieve, SetDesiredProperties, SetDirectory, Store, ValidProperties], STPFSRemoteFile USING [Lookup, LookupResult, ServerData, ServerDataObject], UserCredentials USING [Get]; STPFSRemoteFileImpl: CEDAR MONITOR IMPORTS BasicTime, FS, FSBackdoor, FSName, FSRemoteFileBackdoor, FSReport, GVNames, Process, Rope, RuntimeError, SafeStorage, STP, STPFSRemoteFile, UserCredentials EXPORTS FSRemoteFile -- ought to be removed --, STPFSRemoteFile ~ { <> GMT: TYPE = BasicTime.GMT; ROPE: TYPE = Rope.ROPE; ServerData: TYPE ~ STPFSRemoteFile.ServerData; ServerHandle: TYPE ~ FSRemoteFileBackdoor.ServerHandle; ServerObject: TYPE ~ FSRemoteFileBackdoor.ServerObject; STREAM: TYPE = IO.STREAM; Version: TYPE = FSBackdoor.Version; <> myFlavor: ATOM _ $STP; myServerProcs: FSRemoteFileBackdoor.ServerProcs _ NEW[FSRemoteFileBackdoor.ServerProcsObject _ [STPSweep, STPValidate, STPDelete, STPDo, STPEnumerateForInfo, STPEnumerateForNames, STPGetInfo, STPRename, STPRetrieve, STPStore, STPOpen, STPClose, STPReadWrite]]; initialConnectionTTL: CARD _ 8; upServerTTL: CARD _ 0; -- irrelevant downServerTTL: CARD _ 30; busyServerTTL: CARD _ 10; credentialsErrorTTL: CARD _ 30; maxGrapevineCache: CARDINAL = 7; <> STPDelete: FSRemoteFileBackdoor.DeleteProc -- [h: ServerHandle, file: ROPE, wantedCreatedTime: GMT, case: BOOL, proc: ConfirmProc] -- ~ { matchFound: BOOLEAN _ FALSE; timeSearch: BOOLEAN = (wantedCreatedTime # BasicTime.nullGMT); stpCode: STP.ErrorCode _ noSuchFile; stpH: STP.Handle; Confirm: STP.ConfirmProcType -- [file: ROPE] RETURNS [answer: {do, skip, abort}, localStream: STREAM] -- ~ { info: STP.FileInfo = STP.GetFileInfo[stpH]; created: GMT = FTPTimeToGMT[info.create]; SELECT TRUE FROM matchFound => answer _ abort; (NOT timeSearch) OR (wantedCreatedTime = created) => { answer _ IF (proc = NIL) OR (proc [FSName.VersionFromRope[info.version]]) THEN do ELSE abort; matchFound _ TRUE; }; ENDCASE => answer _ skip; }; InnerDelete: PROC RETURNS [ok: BOOL _ TRUE] ~ { stpH _ NIL; { ENABLE UNWIND => IF stpH # NIL THEN ReturnConnection[h, stpH]; stpH _ GetConnection[h, file, FALSE]; STP.Delete[stpH, file, Confirm ! STP.Error => IF code = noSuchFile THEN CONTINUE ]; IF NOT matchFound THEN { IF timeSearch THEN { file _ FSName.BangStarFile[file]; STP.Delete[stpH, file, Confirm]; }; IF NOT matchFound THEN { ReturnConnection[h, stpH]; stpCode _ noSuchFile; RETURN [FALSE]}; }; }; ReturnConnection[h, stpH]; }; CheckUnimplemented[h, file, case]; IF InnerDelete[ ! STP.Error => {stpCode _ code; CONTINUE}] THEN RETURN; ReportSTPError[stpCode, h, file, wantedCreatedTime]; }; STPDo: FSRemoteFileBackdoor.DoProc -- [h: ServerHandle, cmd: ATOM, arg: REF, result: REF] -- ~ { FSRemoteFileBackdoor.ErrorNotImplemented[h, NIL, "STPDo"]; }; STPEnumerateForInfo: FSRemoteFileBackdoor.EnumerateForInfoProc -- [h: ServerHandle, pattern: ROPE, case: BOOL, proc: InfoProc] -- ~ { NoteInfo: LocalEnumProc -- [stpH: STP.Handle, file: ROPE] RETURNS [continue: BOOL] -- ~ { info: STP.FileInfo ~ STP.GetFileInfo[stpH]; created: BasicTime.GMT ~ FTPTimeToGMT[info.create]; continue _ (proc = NIL) OR (proc[file, info.size, created, FS.tUnspecified]); }; CheckUnimplemented[h, pattern, case]; InnerEnumerate[h, pattern, NoteInfo, FALSE]; }; STPEnumerateForNames: FSRemoteFileBackdoor.EnumerateForNamesProc -- [h: ServerHandle, pattern: ROPE, case: BOOL, proc: NameProc] -- ~ { NoteName: LocalEnumProc -- [stpH: STP.Handle, file: ROPE] RETURNS [continue: BOOL] -- ~ { RETURN[ (proc = NIL) OR (proc[file]) ] }; CheckUnimplemented[h, pattern, case]; InnerEnumerate[h, pattern, NoteName, TRUE]; }; LocalEnumProc: TYPE = PROC [stpH: STP.Handle, file: ROPE] RETURNS [continue: BOOL]; InnerEnumerate: PROC [h: ServerHandle, pattern: ROPE, note: LocalEnumProc, namesOnly: BOOL] ~ { <> stpH: STP.Handle; InnerNote: STP.NoteFileProcType ~ { Process.CheckForAbort[]; <> IF NOT Rope.Match["<*", file] THEN file _ Rope.Concat["<>", file]; <" if they do not support directories. Since FS demands this syntax, we should make sure that it is here.>> continue _ IF note[stpH, file] THEN yes ELSE no; }; InnerBlock: PROC ~ { stpH _ NIL; { ENABLE UNWIND => IF stpH # NIL THEN ReturnConnection[h, stpH]; stpH _ GetConnection[h, pattern, namesOnly]; STP.Enumerate[stpH, pattern, InnerNote]; }; ReturnConnection[h, stpH]; }; InnerBlock[ ! STP.Error => ReportSTPError[code, h, pattern, BasicTime.nullGMT] ]; }; STPGetInfo: FSRemoteFileBackdoor.GetInfoProc -- [h: ServerHandle, file: ROPE, wantedCreatedTime: GMT, case: BOOL] RETURNS [version: Version, bytes: INT, created: GMT, fileType: FS.FileType] -- ~ { result: STPFSRemoteFile.LookupResult; CheckUnimplemented[h, file, case]; fileType _ FS.tUnspecified; [result, version, created, bytes] _ STPFSRemoteFile.Lookup[h, file]; SELECT result FROM ok => { <> IF wantedCreatedTime = BasicTime.nullGMT THEN RETURN; <> IF wantedCreatedTime = created THEN RETURN; <> }; noSuchFile => { <> IF wantedCreatedTime = BasicTime.nullGMT THEN ReportSTPError[noSuchFile, h, file, wantedCreatedTime]; }; ENDCASE => NULL; <> [version, bytes, created] _ STPInfoIgnoringVersionHint[h, file, wantedCreatedTime]; }; STPInfoIgnoringVersionHint: PROC [h: ServerHandle, file: ROPE, wantedCreatedTime: GMT] RETURNS [version: Version, bytes: INT, created: GMT] = { stpH: STP.Handle _ NIL; Note: STP.NoteFileProcType -- [file: ROPE] RETURNS [continue: Continue] -- ~ { info: STP.FileInfo = STP.GetFileInfo[stpH]; created _ FTPTimeToGMT[info.create]; IF NOT timeSearch OR wantedCreatedTime = created THEN { version _ FSName.VersionFromRope[info.version]; bytes _ info.size; matchFound _ TRUE; <> continue _ IF timeSearch THEN no ELSE yes; } ELSE continue _ yes; }; matchFound: BOOL _ FALSE; timeSearch: BOOL = (wantedCreatedTime # BasicTime.nullGMT); stpCode: STP.ErrorCode _ noSuchFile; InnerSTPInfo: PROC RETURNS [found: BOOL _ TRUE] ~ { ENABLE UNWIND => IF stpH # NIL THEN ReturnConnection[h, stpH]; stpH _ NIL; stpH _ GetConnection[h, file, FALSE]; STP.Enumerate[stpH, file, Note ! STP.Error => IF code = noSuchFile THEN CONTINUE ]; IF NOT matchFound THEN { IF timeSearch THEN { file _ FSName.BangStarFile[file]; STP.Enumerate[stpH, file, Note]; }; IF NOT matchFound THEN {stpCode _ noSuchFile; found _ FALSE}; }; ReturnConnection[h, stpH]; }; IF InnerSTPInfo[ ! STP.Error => { stpCode _ code; CONTINUE }] THEN RETURN; ReportSTPError[stpCode, h, file, wantedCreatedTime]; }; STPRename: FSRemoteFileBackdoor.RenameProc -- [h: ServerHandle, fromFile: ROPE, fromCreated: GMT, toFile: ROPE, case: BOOL, proc: ConfirmProc] -- ~ { stpCode: STP.ErrorCode _ noSuchFile; version: Version; InnerRename: PROC RETURNS [ok: BOOL _ TRUE] ~ { stpH: STP.Handle _ NIL; { ENABLE UNWIND => IF stpH # NIL THEN ReturnConnection[h, stpH]; stpH _ GetConnection[h, fromFile, TRUE]; fromFile _ FSName.BangVersionFile[fromFile, version]; STP.Rename[stpH, fromFile, toFile]; }; ReturnConnection[h, stpH]; }; CheckUnimplemented[h, fromFile, case]; CheckUnimplemented[h, toFile, case]; version _ STPGetInfo[h, fromFile, fromCreated, case].version; IF (proc = NIL) OR (proc[version]) THEN { IF InnerRename[! STP.Error => {stpCode _ code; CONTINUE}] THEN RETURN; ReportSTPError[stpCode, h, toFile, BasicTime.nullGMT]; }; }; STPRetrieve: FSRemoteFileBackdoor.RetrieveProc -- [h: ServerHandle, file: ROPE, wantedCreatedTime: GMT, case: BOOL, proc: ConfirmRetrieveProc] -- ~ { matchFound: BOOL _ FALSE; timeSearch: BOOL = (wantedCreatedTime # BasicTime.nullGMT); stpH: STP.Handle _ NIL; stpCode: STP.ErrorCode _ noSuchFile; Confirm: STP.ConfirmProcType ~ { <<[file: ROPE] RETURNS [answer: {do, skip, abort}, localStream: STREAM] >> info: STP.FileInfo = STP.GetFileInfo[stpH]; created: GMT = FTPTimeToGMT[info.create]; SELECT TRUE FROM matchFound => answer _ abort; (NOT timeSearch) OR (wantedCreatedTime = created) => { localStream _ proc[file, info.size, created, FS.tUnspecified]; answer _ IF localStream = NIL THEN abort ELSE do; matchFound _ TRUE; }; ENDCASE => answer _ skip; }; InnerRetrieve: PROC RETURNS [success: BOOL _ TRUE] ~ { stpH _ NIL; { ENABLE UNWIND => IF stpH # NIL THEN ReturnConnection[h, stpH]; stpH _ GetConnection[h, file, FALSE]; STP.Retrieve[stpH, file, Confirm ! STP.Error => IF code = noSuchFile THEN CONTINUE ]; IF NOT matchFound THEN { IF timeSearch THEN { file _ FSName.BangStarFile[file]; STP.Retrieve[stpH, file, Confirm]; }; IF NOT matchFound THEN {stpCode _ noSuchFile; success _ FALSE}; }; }; ReturnConnection[h, stpH]; }; CheckUnimplemented[h, file, case]; IF InnerRetrieve[ ! STP.Error => { stpCode _ code; CONTINUE }] THEN RETURN; ReportSTPError[stpCode, h, file, wantedCreatedTime]; }; STPStore: FSRemoteFileBackdoor.StoreProc -- [h: ServerHandle, file: ROPE, case: BOOL, str: STREAM, created: GMT, proc: ConfirmProc] -- ~ { stpH: STP.Handle _ NIL; stpCode: STP.ErrorCode; Note: STP.NoteFileProcType -- [file: ROPE] RETURNS [continue: Continue] -- ~ { IF proc = NIL THEN RETURN [yes]; RETURN[ IF proc[FSName.VersionFromRope[STP.GetFileInfo[stpH].version]] THEN yes ELSE no ]; }; InnerStore: PROC RETURNS [ok: BOOL _ TRUE] ~ { stpH _ NIL; { ENABLE UNWIND => IF stpH # NIL THEN ReturnConnection[h, stpH]; stpH _ GetConnection[h, file, TRUE]; STP.Store[stpH, file, str, Note, unknown, created]; }; ReturnConnection[h, stpH]; }; CheckUnimplemented[h, file, case]; stpCode _ noSuchFile; IF InnerStore[ ! STP.Error => {stpCode _ code; CONTINUE}] THEN RETURN; ReportSTPError[stpCode, h, file, BasicTime.nullGMT]; }; STPOpen: FSRemoteFileBackdoor.OpenProc -- [h: ServerHandle, cmd: ATOM, file: ROPE, wantedCreatedTime: GMT, case: BOOL, proc: ConfirmRetrieveProc] RETURNS [FileHandle] -- ~ { FSRemoteFileBackdoor.ErrorNotImplemented[h, NIL, "STPOpen"]; RETURN[NIL]; }; STPClose: FSRemoteFileBackdoor.CloseProc -- [h: ServerHandle, fileHandle: FileHandle] -- ~ { FSRemoteFileBackdoor.ErrorNotImplemented[h, NIL, "STPClose"]; }; STPReadWrite: FSRemoteFileBackdoor.RWProc -- [h: ServerHandle, fileHandle: FileHandle, cmd: ATOM, bytePos: CARD, block: REF TEXT] RETURNS [bytesTransferred: CARD] -- ~ { FSRemoteFileBackdoor.ErrorNotImplemented[h, NIL, "STPReadWrite"]; }; <