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)
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] = {
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
result: FileLookup.Result;
tryBangH: BOOLFALSE;
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 {
the file found has the right create date, or there was no create time but we found it
CWF.SWF2[targetFileName, "%s!%d"L, prefix, @remoteVersion];
Cleanup[];
RETURN[
foundCorrectVersion, remoteVersion, remoteCreateTime, remoteByteLength];
};
otherwise do the FTP search
};
noSuchName => {
this file does not exist
IF tryBangH OR wantExplicitVersion THEN {
we probed with !H, there is no file
we probed with explicit version, there is no file
FillInErrorTargetFile[targetFileName, prefix, wantExplicitVersion, version];
Cleanup[];
RETURN[notFound, 0, 0, 0];
};
if we probed with a version hint, do the FTP search
};
noResponse, noSuchPort =>{
no file lookup server or it does not reply, do the FTP search
};
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: STRINGIF 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 = {
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
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 the date in the df file agrees with date on remote server
IF createtime > 0 AND createtime = date THEN {
remoteVersion ← vers;
remoteCreateTime ← date;
remoteByteLength ← info.size;
fres ← foundCorrectVersion;
found ← TRUE;
Subr.strcpy[foundFileName, file];
RETURN;
}
if there is no date in the df file
ELSE IF createtime = 0 THEN {
remoteVersion ← vers;
remoteCreateTime ← date;
remoteByteLength ← info.size;
found ← TRUE;
Subr.strcpy[foundFileName, file];
RETURN;
};
if we were given a date but it did not agree, keep looking
};
{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] = {
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
sfn: LONG STRINGNIL;
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
the file found has the right create date OR there was no create time but we found it
fres ← foundCorrectVersion;
GO TO return;
};
noSuchName => {
this file does not exist
fres ← notFound;
remoteVersion ← remoteCreateTime ← remoteByteLength ← 0;
GO TO return;
};
noResponse, noSuchPort =>{
no file lookup server or it does not reply, do the FTP search
[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 = {
NOTE: Desired properties have been set
only called once
stphandle is passed in
NoteFileProcType: TYPE = PROC [file: LONG STRING] RETURNS [continue: Continue];
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;
remoteCreateTime ← date;
remoteByteLength ← info.size;
remoteVersion ← vers;
if the date in the df file agrees with date on remote server
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 => {
see if the file name works without the !* or ;*
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];
};
}.