// IfsFtpUtil.bcpl -- Utility routines // Copyright Xerox Corporation 1979, 1980, 1981, 1982 // Last modified May 11, 1982 4:26 PM by Taft get "Pup0.decl" get "Pup1.decl" get "PupRTP.decl" get "Ifs.decl" get ErrRec, ftpEc, errorString from "IfsSystemInfo.decl" get "IfsFiles.decl" get "IfsDirs.decl" get "IfsFtpProt.decl" external [ // outgoing procedures FtpSMakeSFIL; FtpSSendMark FtpSFillPLFromLD; FtpSCheckAccess; FtpSCheckConnection // incoming procedures ExtractSubstring; StringCompare; ExpandTemplate IFSPrintError; Login; Connect; MoveBlock SysFree; FreePointer LockTransferLeaderPage; GetBufferForFD; DestroyFD FTPM; FreePList; InitPList LookupErrorCode // incoming statics CtxRunning ] //--------------------------------------------------------------------------- let FtpSSendMark(mark, ec, arg0, arg1, arg2, arg3, arg4) = valof //--------------------------------------------------------------------------- // Expands ec into an Ftp error code and string. // The next step is usually to return false, // so this routine supplies the 'false' value allowing you to say: // unless IFSDeleteFile(...) resultis FtpSSendMark(...) [ let errRec = LookupErrorCode(ec) FTPM(mark, errRec>>ErrRec.ftpEc, lv errRec>>ErrRec.errorString, false, arg0, arg1, arg2, arg3, arg4) SysFree(errRec) resultis false ] //--------------------------------------------------------------------------- and FtpSCheckConnection() = valof //--------------------------------------------------------------------------- // Do not call from MTP server; only FTP server [ if CtxRunning>>FtpCtx.bspSoc>>RTPSoc.state ne stateOpen then [ if CtxRunning>>FtpCtx.fd ne 0 then CtxRunning>>FtpCtx.fd = DestroyFD(CtxRunning>>FtpCtx.fd) resultis false ] resultis true ] //--------------------------------------------------------------------------- and FtpSCheckAccess(pl) = valof //--------------------------------------------------------------------------- // Check login/connect parameters in pl. [ let ui = CtxRunning>>FtpCtx.userInfo // Login parameters let ec = Login(pl>>PL.UNAM, pl>>PL.UPSW, ui) // Connect parameters if ec eq 0 then ec = Connect(pl>>PL.CNAM, pl>>PL.CPSW, ui) resultis ec eq 0? true, FtpSSendMark(markNo, ec) ] //--------------------------------------------------------------------------- and FtpSMakeSFIL(pl) be //--------------------------------------------------------------------------- // Builds a serverFilename from the information in pl. // The result is left in pl>>PL.SFIL. [ // If there is no name body, construct a blank one if pl>>PL.NAMB eq 0 then pl>>PL.NAMB = ExtractSubstring("") // If there is no server filename, construct one. // The Version property isn't correctly handled. A version supplied // in a PL will only be used as a default if no ServerFilename was // supplied. The proper implementation is to handle it the way // default directories are: pass the default version from the PL to // the directory module, where CreateFD can decide whether it is needed. if pl>>PL.SFIL eq 0 then pl>>PL.SFIL = ExpandTemplate((pl>>PL.VERS eq 0? "$S", "$S!$S"), pl>>PL.NAMB, pl>>PL.VERS) // If a directory is specified, strip off the outer < > if present if pl>>PL.DIRE ne 0 then [ let dir = pl>>PL.DIRE if dir>>String.char↑(dir>>String.length) eq $> then dir>>String.length = dir>>String.length -1 if dir>>String.char↑1 eq $< then [ pl>>PL.DIRE = ExtractSubstring(dir, 2) SysFree(dir) ] ] ] //--------------------------------------------------------------------------- and FtpSFillPLFromLD(remotePL, reportDamage; numargs na) = valof //--------------------------------------------------------------------------- // Creates and returns a PL from the properties of the file described by FtpCtx.fd. // Returns zero if the file has gone away. [ let dprp = remotePL>>PL.DPRP // desired properties if dprp eq 0 then dprp = -1 // if none specified, request all properties let pl = InitPList() let fd = CtxRunning>>FtpCtx.fd let dr = fd>>FD.dr // first generate properties that can be extracted from the FD if dprp<<DPRP.SFIL then pl>>PL.SFIL = ExtractSubstring(lv dr>>DR.pathName) if dprp<<DPRP.DEVI then pl>>PL.DEVI = ExtractSubstring(fd>>FD.fs>>IFS.id) if dprp<<DPRP.DIRE then pl>>PL.DIRE = ExtractSubstring(lv dr>>DR.pathName, 2, fd>>FD.lenSubDirString-1) if dprp<<DPRP.NAMB then pl>>PL.NAMB = ExtractSubstring(lv dr>>DR.pathName, fd>>FD.lenSubDirString+1, fd>>FD.lenBodyString-1) if dprp<<DPRP.VERS then pl>>PL.VERS = ExtractSubstring(lv dr>>DR.pathName, fd>>FD.lenBodyString+1) // if no other properties desired, don't need to read the leader page manifest requiresLeaderPage = 100000B rshift offset DPRP.TYPE % 100000B rshift offset DPRP.BYTE % 100000B rshift offset DPRP.SIZE % 100000B rshift offset DPRP.AUTH % 100000B rshift offset DPRP.CDAT % 100000B rshift offset DPRP.RDAT % 100000B rshift offset DPRP.WDAT % 100000B rshift offset DPRP.CSUM if (dprp & requiresLeaderPage) ne 0 then [ let ild = GetBufferForFD(fd) let ec = LockTransferLeaderPage(fd, ild) // read if ec ne 0 then [ SysFree(ild); resultis FreePList(pl) ] if dprp<<DPRP.TYPE then pl>>PL.TYPE = ild>>ILD.type if dprp<<DPRP.BYTE then pl>>PL.BYTE = ild>>ILD.byteSize if dprp<<DPRP.AUTH then pl>>PL.AUTH = ExtractSubstring(lv ild>>ILD.author) if dprp<<DPRP.CDAT then MoveBlock(lv pl>>PL.CDAT, lv ild>>LD.created, 2) if dprp<<DPRP.RDAT then MoveBlock(lv pl>>PL.RDAT, lv ild>>LD.read, 2) if dprp<<DPRP.WDAT then MoveBlock(lv pl>>PL.WDAT, lv ild>>LD.written, 2) if dprp<<DPRP.SIZE then [ let siz = lv pl>>PL.SIZE let fa = lv ild>>LD.hintLastPageFa let lnBytes = fd>>FD.fs>>IFS.logPageLength +1 let numPages = fa>>FA.pageNumber -1 // don't count leader page unless numPages eq -1 do [ siz!0 = numPages rshift (16-lnBytes) siz!1 = numPages lshift lnBytes + fa>>FA.charPos ] ] if dprp<<DPRP.CSUM then pl>>PL.CSUM = ild>>ILD.checksum if na gr 1 & reportDamage & ild>>ILD.damaged then FtpSSendMark(markComment, ecFileDamaged, lv dr>>DR.pathName) SysFree(ild) ] resultis pl ]