DIRECTORY ConvertUnsafe: TYPE USING[ToRope], CWF: TYPE USING [SWF2, SWF3, SWF4], DateAndTimeUnsafe: TYPE USING [Parse, Unintelligible], FileLookup: TYPE USING[LookupFile, Result], FQ: TYPE USING[Result], LongString: TYPE USING[StringToDecimal], Rope: TYPE USING[ROPE], UnsafeSTP: TYPE USING [DesiredProperties, Enumerate, Error, FileInfo, GetFileInfo, Handle, NoteFileProcType, SetDesiredProperties], STPSubr: TYPE USING [Connect, ForceClosed, HandleSTPError], Subr: TYPE USING [AllocateString, EndsIn, FreeString, Prefix, strcpy, TTYProcs]; FQImpl: PROGRAM IMPORTS ConvertUnsafe, CWF, DateAndTimeUnsafe, FileLookup, LongString, STP: UnsafeSTP, STPSubr, Subr EXPORTS FQ = { FileQuery: PUBLIC PROC [host, directory, shortname: LONG STRING, version: CARDINAL, createtime: LONG CARDINAL, wantExplicitVersion: BOOL,h: Subr.TTYProcs, targetFileName: LONG STRING, useRopes: BOOL] RETURNS [fres: FQ.Result, remoteVersion: CARDINAL, remoteCreateTime, remoteByteLength: LONG CARDINAL] = { result: FileLookup.Result; tryBangH: BOOL _ FALSE; server, file: Rope.ROPE; sfn: LONG STRING _ Subr.AllocateString[100]; prefix: LONG STRING _ Subr.AllocateString[100]; Cleanup: PROC = {Subr.FreeString[sfn]; Subr.FreeString[prefix]}; {ENABLE UNWIND => Cleanup[]; CWF.SWF3[prefix, "[%s]<%s>%s"L, host, directory, shortname]; {-- begin block for exit skipThis IF NOT useRopes THEN GOTO skipThis; IF version > 0 AND (createtime ~= 0 OR wantExplicitVersion) THEN CWF.SWF3[sfn, "<%s>%s!%u"L, directory, shortname, @version] ELSE { tryBangH _ TRUE; CWF.SWF2[sfn, "<%s>%s!H"L, directory, shortname]; }; server _ ConvertUnsafe.ToRope[host]; file _ ConvertUnsafe.ToRope[sfn]; [result: result, version: remoteVersion, create: remoteCreateTime, count: remoteByteLength] _ FileLookup.LookupFile[server: server, file: file]; server _ file _ NIL; -- free as soon as possible SELECT result FROM ok => { IF createtime = 0 OR createtime = remoteCreateTime THEN { CWF.SWF2[targetFileName, "%s!%d"L, prefix, @remoteVersion]; Cleanup[]; RETURN[ foundCorrectVersion, remoteVersion, remoteCreateTime, remoteByteLength]; }; }; noSuchName => { IF tryBangH OR wantExplicitVersion THEN { FillInErrorTargetFile[targetFileName, prefix, wantExplicitVersion, version]; Cleanup[]; RETURN[notFound, 0, 0, 0]; }; }; noResponse, noSuchPort =>{ }; ENDCASE => ERROR; EXITS skipThis => NULL; }; [fres, remoteVersion, remoteCreateTime, remoteByteLength] _ EnumerateWithSTP[host, directory, shortname, version, createtime, wantExplicitVersion, h, prefix, targetFileName]; }; -- of ENABLE UNWIND Cleanup[]; }; EnumerateWithSTP: PROC [host, directory, shortname: LONG STRING, version: CARDINAL, createtime: LONG CARDINAL, wantExplicitVersion: BOOL, h: Subr.TTYProcs, prefix, targetFileName: LONG STRING] RETURNS[fres: FQ.Result, remoteVersion: CARDINAL, remoteCreateTime, remoteByteLength: LONG CARDINAL] = { stphandle: STP.Handle; found: BOOL; highdate: LONG CARDINAL _ 0; highversion: CARDINAL _ 0; desiredProperties: STP.DesiredProperties _ ALL[FALSE]; smashstp: STP.Handle _ NIL; vstring: STRING _ IF Subr.Prefix[host, "maxc"L] THEN ";"L ELSE "!"L; sfn: LONG STRING _ Subr.AllocateString[100]; foundFileName: LONG STRING _ Subr.AllocateString[100]; CleanupStrings: PROC = {Subr.FreeString[sfn]; Subr.FreeString[foundFileName]}; EnumProcessFile: STP.NoteFileProcType = { vers: CARDINAL _ 0; date: LONG CARDINAL; info: STP.FileInfo _ STP.GetFileInfo[stphandle]; continue _ yes; IF info.version ~= NIL AND info.version.length > 0 THEN vers _ LongString.StringToDecimal[info.version]; date _ DateAndTimeUnsafe.Parse[info.create ! DateAndTimeUnsafe.Unintelligible => { -- this can actually happen e.g. time = 0 (or 1937) date _ 0; CONTINUE; }; ].dt; IF vers > highversion THEN { highversion _ vers; highdate _ date; }; IF found THEN RETURN[yes]; IF createtime > 0 AND createtime = date THEN { remoteVersion _ vers; remoteCreateTime _ date; remoteByteLength _ info.size; fres _ foundCorrectVersion; found _ TRUE; Subr.strcpy[foundFileName, file]; RETURN; } ELSE IF createtime = 0 THEN { remoteVersion _ vers; remoteCreateTime _ date; remoteByteLength _ info.size; found _ TRUE; Subr.strcpy[foundFileName, file]; RETURN; }; }; {ENABLE UNWIND => CleanupStrings[]; found _ FALSE; remoteCreateTime _ remoteByteLength _ remoteVersion _ 0; IF version > 0 AND createtime = 0 AND wantExplicitVersion THEN CWF.SWF4[sfn, "<%s>%s%s%u"L, directory, shortname, vstring, @version] ELSE IF createtime = 0 THEN -- take highest version CWF.SWF3[sfn, "<%s>%s%sH"L, directory, shortname, vstring] ELSE -- search for all CWF.SWF3[sfn, "<%s>%s%s**"L, directory, shortname, vstring]; desiredProperties[directory] _ TRUE; desiredProperties[nameBody] _ TRUE; desiredProperties[version] _ TRUE; desiredProperties[createDate] _ TRUE; desiredProperties[size] _ TRUE; DO stphandle _ STPSubr.Connect[host: host, onlyOne: TRUE, h: h]; STP.SetDesiredProperties[stphandle, desiredProperties]; STP.Enumerate[stphandle, sfn, EnumProcessFile ! STP.Error => SELECT code FROM noSuchFile, illegalFileName => GOTO notFound; connectionClosed => {smashstp _ stphandle; CONTINUE}; ENDCASE => IF STPSubr.HandleSTPError[stphandle, code, error, h] THEN RETRY ]; IF smashstp ~= NIL THEN smashstp _ STPSubr.ForceClosed[smashstp] ELSE EXIT; ENDLOOP; IF found THEN { CWF.SWF2[targetFileName, "[%s]%s"L, host, foundFileName]; CleanupStrings[]; RETURN[foundCorrectVersion, remoteVersion, remoteCreateTime, remoteByteLength]; }; FillInErrorTargetFile[targetFileName, prefix, wantExplicitVersion, version]; CleanupStrings[]; RETURN[foundWrongVersion, highversion, highdate, 0]; -- enumerated but didn't find it EXITS notFound => { FillInErrorTargetFile[targetFileName, prefix, wantExplicitVersion, version]; CleanupStrings[]; RETURN[notFound, 0, 0, 0]; -- no such file, did not enumerate }; }; -- of ENABLE UNWIND }; FillInErrorTargetFile: PROC[targetFileName, prefix: LONG STRING, wantExplicitVersion: BOOL, version: CARDINAL] = { IF wantExplicitVersion THEN CWF.SWF2[targetFileName, "%s!%d"L, prefix, @version] ELSE Subr.strcpy[targetFileName, prefix]; }; FileQueryBangH: PUBLIC PROC [host, directory, shortname: LONG STRING, createtime: LONG CARDINAL, h: Subr.TTYProcs, useRopes: BOOL] RETURNS [fres: FQ.Result, remoteVersion: CARDINAL, remoteCreateTime, remoteByteLength: LONG CARDINAL] = { sfn: LONG STRING _ NIL; result: FileLookup.Result; IF NOT useRopes THEN { [fres, remoteVersion, remoteCreateTime, remoteByteLength] _ EnumerateWithSTPBangH[host, directory, shortname, createtime, h]; RETURN; -- can't use FileLookup because of Ropes }; sfn _ Subr.AllocateString[100]; {ENABLE UNWIND => {Subr.FreeString[sfn]}; CWF.SWF2[sfn, "<%s>%s!H"L, directory, shortname]; [result: result, version: remoteVersion, create: remoteCreateTime, count: remoteByteLength] _ FileLookup.LookupFile[server: ConvertUnsafe.ToRope[host], file: ConvertUnsafe.ToRope[sfn]]; SELECT result FROM ok => { fres _ foundWrongVersion; IF (createtime ~= 0 AND createtime = remoteCreateTime) OR createtime = 0 THEN fres _ foundCorrectVersion; GO TO return; }; noSuchName => { fres _ notFound; remoteVersion _ remoteCreateTime _ remoteByteLength _ 0; GO TO return; }; noResponse, noSuchPort =>{ [fres, remoteVersion, remoteCreateTime, remoteByteLength] _ EnumerateWithSTPBangH[host, directory, shortname, createtime, h]; }; ENDCASE => ERROR; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[sfn]; }; EnumerateWithSTPBangH: PROC[host, directory, shortname: LONG STRING, createtime: LONG CARDINAL, h: Subr.TTYProcs] RETURNS[fres: FQ.Result, remoteVersion: CARDINAL, remoteCreateTime, remoteByteLength: LONG CARDINAL] = { stphandle: STP.Handle; desiredProperties: STP.DesiredProperties _ ALL[FALSE]; smashstp: STP.Handle _ NIL; vstring: STRING _ [1]; sfn: LONG STRING _ Subr.AllocateString[100]; EnumProcessFile: STP.NoteFileProcType = { vers: CARDINAL _ 0; date: LONG CARDINAL; info: STP.FileInfo _ STP.GetFileInfo[stphandle]; continue _ yes; IF info.version ~= NIL AND info.version.length > 0 THEN vers _ LongString.StringToDecimal[info.version]; date _ DateAndTimeUnsafe.Parse[info.create ! DateAndTimeUnsafe.Unintelligible => { date _ 0; CONTINUE}; ].dt; remoteCreateTime _ date; remoteByteLength _ info.size; remoteVersion _ vers; IF createtime > 0 AND createtime = date THEN fres _ foundCorrectVersion ELSE IF createtime = 0 THEN -- if there is no date in the df file fres _ foundCorrectVersion ELSE -- if we were given a date but it did not agree fres _ foundWrongVersion; }; vstring.length _ 1; vstring[0] _ IF Subr.Prefix[host, "maxc"L] THEN '; ELSE '!; {ENABLE UNWIND => {Subr.FreeString[sfn]}; fres _ notFound; remoteCreateTime _ remoteByteLength _ remoteVersion _ 0; CWF.SWF3[sfn, "<%s>%s%sH"L, directory, shortname, vstring]; desiredProperties[version] _ TRUE; desiredProperties[createDate] _ TRUE; desiredProperties[size] _ TRUE; DO stphandle _ STPSubr.Connect[host: host, onlyOne: TRUE, h: h]; STP.SetDesiredProperties[stphandle, desiredProperties]; STP.Enumerate[stphandle, sfn, EnumProcessFile ! STP.Error => SELECT code FROM noSuchFile => GOTO notFound; illegalFileName => { IF Subr.EndsIn[sfn, "!H"L] THEN { sfn.length _ sfn.length - 2; LOOP; -- try again without it (this is for Twinkle) } ELSE CONTINUE -- second try failed }; connectionClosed => { smashstp _ stphandle; CONTINUE; } ENDCASE => IF STPSubr.HandleSTPError[stphandle, code, error, h] THEN RETRY ]; IF smashstp ~= NIL THEN smashstp _ STPSubr.ForceClosed[smashstp] ELSE EXIT; ENDLOOP; EXITS notFound => { remoteVersion _ remoteCreateTime _ remoteByteLength _ 0; fres _ notFound; -- no such file, did not enumerate }; }; -- of ENABLE UNWIND Subr.FreeString[sfn]; }; }. FQImpl.Mesa last edit February 8, 1983 4:31 pm last edit May 23, 1983 6:34 pm, Russ Atkinson (short STRING to LONG STRING) be careful about useRopes: ropes are not available for BringOver in the boot file if createtime ~= 0 then looks for a file with that create time; uses version number as a hint; result is foundCorrectVersion if the file is found; foundWrongVersion if a file is found but not that one; notFound if the file or server does not exist at all if createtime = 0 and wantExplicitVersion THEN looks for a file with that version number result is foundCorrectVersion if the file is found notFound if the file or server does not exist at all if createtime = 0 and NOT wantExplicitVersion THEN looks for any file of that name (!H) result is foundCorrectVersion if the file is found notFound if the file or server does not exist at all foundCorrectVersion returns correct version and time targetFileName has a full filename including version number foundWrongVersion returns highest version and time targetFileName has a full filename without version number notFound returns no version and no time targetFileName has a full filename without version number unless wantExplicitVersion = TRUE, in which case it will have one the file found has the right create date, or there was no create time but we found it otherwise do the FTP search this file does not exist we probed with !H, there is no file we probed with explicit version, there is no file if we probed with a version hint, do the FTP search no file lookup server or it does not reply, do the FTP search NoteFileProcType: TYPE = PROC [file: LONG STRING] RETURNS [continue: Continue]; NOTE: Desired properties have been set; only called once unless createtime ~= 0; stphandle is passed in if the date in the df file agrees with date on remote server if there is no date in the df file if we were given a date but it did not agree, keep looking just check the highest version if createtime > 0 then looks for !h in that version foundCorrectVersion if found foundWrongVersion if not found in that date notFound if not there at all if createtime = 0 then look for any !h foundCorrectVersion if found notFound if not there at all foundCorrectVersion returns correct version and time foundWrongVersion returns highest version and time notFound returns no version and no time the file found has the right create date OR there was no create time but we found it this file does not exist no file lookup server or it does not reply, do the FTP search NOTE: Desired properties have been set only called once stphandle is passed in NoteFileProcType: TYPE = PROC [file: LONG STRING] RETURNS [continue: Continue]; this can actually happen e.g. time = 0 (or 1937) if the date in the df file agrees with date on remote server see if the file name works without the !* or ;* Ê u˜šœ ™ Jšœ"™"JšœK™K—J˜šÏk ˜ Jšœœœ ˜"Jšœœœ˜#Jšœœœ˜6Jšœ œœ˜+Jšœœœ ˜Jšœ œœ˜(Jšœœœœ˜šœ œ˜Jšœm˜m—Jšœ œœ(˜;Jšœœœ@˜PJ˜—šœœ˜š˜Jšœœ-œ˜]—Jšœœ˜—J˜J˜šÏn œœ˜Jšœœœ œœœœ#œœ œ˜±Jš œœœ&œœ˜iJšœQ™QJ˜Jšœÿ™ÿJšœ.™.Jšœ)™)Jšœ2™2Jšœ5™5Jšœ2™2Jšœ$™$Jšœ2™2Jšœ5™5J˜Jšœ4™4Jšœ;™;Jšœ2™2Jšœ9™9Jšœ'™'Jšœ9™9JšœA™AJ˜J˜Jšœ œœ˜Jšœœ˜Jšœœœ˜,Jšœœœ˜/Jšžœœ3˜@šœœœ˜Jšœ9˜<šœÏc ˜!Jšœœ œœ ˜#šœ œœ˜;Jšœœ8˜@šœ˜Jšœ œ˜Jšœ.˜1J˜——J˜$J˜!˜CJ˜M—JšœœŸ˜0šœ˜˜šœœœ˜9JšœU™UJšœ8˜;Jšœ ˜ šœ˜JšœH˜H—J˜—Jšœ™J˜—˜Jšœ™šœ œœ˜)Jšœ#™#Jšœ1™1J˜LJšœ ˜ Jšœ˜J˜—Jšœ3™3J˜—˜Jšœ=™=J˜—Jšœœ˜—Jšœ œ˜J˜—˜<˜,J˜E——JšœŸœ˜—Jšœ ˜ J˜J˜—šžœ˜Jšœœœ œœœœ,œœ˜ªJš œœœ&œœ˜hJšœ œ˜Jšœœ˜ Jšœ œœ˜Jšœ œ˜Jšœœœœ˜6Jšœ œ œ˜Jš œ œœœœ˜DJšœœœ˜,Jšœœœ˜6Jšžœœ:˜Nšœœ˜)JšœO™OJšœg™gJšœœ˜Jšœœœ˜Jšœœ œ˜0J˜šœœœ˜7J˜0—˜*šœ(Ÿ3˜[J˜ Jšœ˜ J˜—J˜—šœœ˜J˜J˜J˜—Jšœœœ˜Jšœ<™<šœœœ˜.J˜J˜J˜J˜Jšœœ˜ J˜!Jšœ˜J˜—Jšœ"™"šœœœ˜J˜J˜J˜Jšœœ˜ J˜!Jšœ˜J˜—Jšœ:™:J˜J˜—šœœœ˜#Jšœœ˜J˜8šœ œœ˜>JšœB˜E—šœœœŸ˜3Jšœ7˜:—šœŸ˜Jšœ9˜<—Jšœœ˜$Jšœœ˜#Jšœœ˜"Jšœ œ˜%Jšœœ˜š˜Jšœ1œ˜=Jšœ4˜7šœ*˜-šœœ ˜šœ˜Jšœœ ˜-Jšœ+œ˜5Jšœœ3œ˜J—J˜——šœ ˜Jšœ)˜-Jšœœ˜ —Jšœ˜—šœœ˜Jšœ7˜:Jšœ˜JšœI˜OJ˜—J˜LJšœ˜Jšœ/Ÿ ˜Uš˜˜ J˜LJšœ˜JšœŸ"˜=J˜——JšœŸœ˜—J˜J˜J˜—š žœœœœœ˜[Jšœ œ˜šœ˜Jšœ1˜4—š˜J˜$—J˜J˜—šžœœ˜Jš œœœœœœ˜gJš œœœ&œœ˜iJšœ™šœ3™3Jšœ™Jšœ+™+Jšœ™—šœ&™&Jšœ™Jšœ™Jšœ4™4Jšœ2™2Jšœ'™'—J˜Jšœœœœ˜J˜šœœ œ˜˜