<> <> <> <> <> <> <> <> <<>> DIRECTORY BasicTime USING [GMT, nullGMT, ToPupTime, Update], CedarProcess USING [Fork, ForkableProc, Process], Endian USING [FFromCard], FS USING [ComponentPositions, Error, ExpandName, FileInfo], PupBuffer USING [Buffer, FileLookupReply], PupSocket USING [CreateServer, Destroy, ExtractRope, FreeBuffer, Get, ReturnToSender, SetUserHWords, SetUserSize, Socket, waitForever], PupType USING [fileLookup, fileLookupError, fileLookupReply], PupWKS USING [fileLookup], Rope USING [Cat, Find, Index, Length, Replace, ROPE, Substr], STPServerFileTranslation USING [FindNamedTranslator, NamedTranslator], STPServerPrivate USING [CurrentVersion, FileName, NameMapDirection, NameMapList], UserProfile USING [CallWhenProfileChanges, ListOfTokens, ProfileChangeReason]; STPServerAuxImpl: CEDAR MONITOR IMPORTS BasicTime, CedarProcess, Endian, FS, PupSocket, Rope, STPServerPrivate, UserProfile, STPServerFileTranslation EXPORTS STPServerPrivate ~ BEGIN OPEN STPServerPrivate; <> nameMaps: NameMapList _ NIL; GMT: TYPE ~ BasicTime.GMT; ROPE: TYPE ~ Rope.ROPE; LOR: TYPE ~ LIST OF ROPE; BothFromOne: PUBLIC PROC [oneName: ROPE, direction: NameMapDirection] RETURNS [both: FileName] ~ { otherName: ROPE _ oneName; otherLength: INT _ otherName.Length[]; FOR nms: NameMapList _ nameMaps, nms.rest WHILE nms # NIL DO find: ROPE ~ SELECT direction FROM localToRemote => nms.first.local, remoteToLocal => nms.first.remote, ENDCASE => ERROR; repl: ROPE ~ SELECT direction FROM localToRemote => nms.first.remote, remoteToLocal => nms.first.local, ENDCASE => ERROR; start: INT ~ otherName.Find[s2: find, case: FALSE]; cutLength: INT ~ find.Length[]; IF start >= 0 THEN { otherName _ otherName.Replace[start: start, len: cutLength, with: repl]; EXIT; }; ENDLOOP; both _ SELECT direction FROM localToRemote => [local: oneName, remote: otherName], remoteToLocal => [local: otherName, remote: oneName], ENDCASE => ERROR; }; RealName: PROC [remoteName: ROPE] RETURNS [realName: ROPE _ NIL, translated: BOOL _ FALSE] ~ { fullFName: ROPE _ NIL; cp: FS.ComponentPositions; namedTranslator: STPServerFileTranslation.NamedTranslator _ NIL; hostNameLength: INT _ 0; [fullFName, cp] _ FS.ExpandName[remoteName]; namedTranslator _ STPServerFileTranslation.FindNamedTranslator[fullFName, cp.dir.start, cp.dir.length]; IF namedTranslator = NIL OR cp.subDirs.length = 0 THEN RETURN [realName: BothFromOne[remoteName, remoteToLocal].local, translated: FALSE]; hostNameLength _ Rope.Index[s1: fullFName, pos1: cp.subDirs.start, s2: ">"] - cp.subDirs.start; realName _ Rope.Cat["[", Rope.Substr[fullFName, cp.subDirs.start, hostNameLength], "]<", Rope.Substr[fullFName, cp.subDirs.start+hostNameLength+1]]; translated _ TRUE; }; NoteProfile: PROC [reason: UserProfile.ProfileChangeReason] --UserProfile.ChangeProc-- ~ { maps: LOR _ UserProfile.ListOfTokens["STPServer.NameMappings", NIL]; newMaps: NameMapList _ NIL; FOR maps _ maps, maps.rest.rest WHILE maps # NIL AND maps.rest # NIL DO remote: ROPE ~ maps.first; local: ROPE ~ maps.rest.first; newMaps _ CONS[[local: local, remote: remote], newMaps]; ENDLOOP; IF maps # NIL THEN ERROR; nameMaps _ newMaps; }; <> <<>> socket: PupSocket.Socket _ NIL; singleProcess: CedarProcess.Process _ NIL; StartSingle: PUBLIC ENTRY PROC = { IF singleProcess = NIL THEN { socket _ PupSocket.CreateServer[ local: PupWKS.fileLookup, recvBuffers: 5, getTimeout: PupSocket.waitForever ]; singleProcess _ CedarProcess.Fork[ SinglePacketListener, NIL, [priority: foreground, usePriority: TRUE]]; }; }; StopSingle: PUBLIC ENTRY PROC = { IF singleProcess # NIL THEN { PupSocket.Destroy[socket]; socket _ NIL; }; }; SinglePacketListener: CedarProcess.ForkableProc = TRUSTED { ENABLE UNWIND => singleProcess _ NIL; DO b: PupBuffer.Buffer = PupSocket.Get[socket]; IF b = NIL THEN EXIT; SELECT b.type FROM PupType.fileLookup => { name: ROPE _ Rope.Cat["[]", PupSocket.ExtractRope[b]]; fileLen: INT _ 0; fileDate: GMT _ BasicTime.nullGMT; translated: BOOL _ FALSE; [name, translated] _ RealName[name]; [fullFName: name, created: fileDate, bytes: fileLen] _ FS.FileInfo[name: name ! FS.Error => { b.type _ PupType.fileLookupError; b.hWord[0] _ error.group.ORD; PupSocket.SetUserHWords[b, 1]; CONTINUE; }; ]; IF fileDate # BasicTime.nullGMT AND fileLen >= 0 THEN { IF translated THEN { fileLen _ (fileLen+999)/1000*1000; fileDate _ BasicTime.Update[fileDate, 1]; }; b.fileLookupReply.version _ CurrentVersion[name]; b.fileLookupReply.createTime _ Endian.FFromCard[BasicTime.ToPupTime[fileDate]]; b.fileLookupReply.length _ Endian.FFromCard[fileLen]; b.type _ PupType.fileLookupReply; PupSocket.SetUserSize[b, SIZE[PupBuffer.FileLookupReply]]; }; PupSocket.ReturnToSender[b]; }; ENDCASE => PupSocket.FreeBuffer[b]; ENDLOOP; singleProcess _ NIL; }; <<>> <> Init: PROC ~ { UserProfile.CallWhenProfileChanges[NoteProfile]; }; Init[]; END.