// IfsLookupFileSwap.bcpl -- low-cost file cache validation for CIFS
// Copyright Xerox Corporation 1982
// Last modified August 6, 1982  6:04 PM by Boggs

get "IfsLookupFileServ.decl"
get "Ifs.decl"
get "AltoFileSys.d"
get "IfsDirs.decl"

external
[
// outgoing procedures
HandleLookupFilePBI

// incoming procedures
LookupIFSFile; GetBufferForFD; LockTransferLeaderPage; DestroyFD
ExchangePorts; CompletePup; ReleasePBI
ByteBlt; MoveBlock; SysFree; Umax

// incoming statics
@lfs
]

//----------------------------------------------------------------------------
let HandleLookupFilePBI(pbi) be
//----------------------------------------------------------------------------
// Always disposes of pbi.
[
if pbi>>PBI.pup.type ne ptLookupFileRequest %
 pbi>>PBI.pup.dPort.host eq 0 then [ ReleasePBI(pbi); return ]
lfs>>LFS.active = true
ExchangePorts(pbi)
let fd, ec = 0, etNoSuchFile
test valof
   [  // This block returns true iff the lookup is successful
   // The following check prevents the directory from ever being defaulted,
   // which would yield undefined results since the current context is
   // the EventMgr, which is not an RSCtx.
   let length = pbi>>PBI.pup.length-pupOvBytes
   if length le 0 % pbi>>PBI.pup.bytes↑1 ne $< resultis false

   // Slide text down by 1 byte and insert length to make a BCPL string;
   // and look that string up as an IFS filename.
   ByteBlt(lv pbi>>LFPBI.string, 1, lv pbi>>PBI.pup.bytes, 0, length)
   pbi>>LFPBI.string.length = length
   fd = LookupIFSFile(lv pbi>>LFPBI.string, lcVHighest, lv ec, 0, "")
   pbi>>PBI.pup.sPort.socket↑2 = socketLookupFile  // fix clobbered word
   if fd eq 0 resultis false  // no such file

   // Read leader page to get properties
   let buffer = GetBufferForFD(fd)
   ec = LockTransferLeaderPage(fd, buffer)
   MoveBlock(lv pbi>>LFPBI.reply.created, lv buffer>>LD.created, 2)
   let pages = Umax(buffer>>LD.hintLastPageFa.pageNumber, 1) -1  // don't count leader page
   let lnBytesPerPage = fd>>FD.fs>>IFS.logPageLength +1
   pbi>>LFPBI.reply.byteLength↑0 = pages rshift (16-lnBytesPerPage)
   pbi>>LFPBI.reply.byteLength↑1 = pages lshift lnBytesPerPage +
    buffer>>LD.hintLastPageFa.charPos
   SysFree(buffer)
   pbi>>LFPBI.reply.version = fd>>FD.version
   resultis ec eq 0
   ]
   ifso CompletePup(pbi, ptLookupFileReply, pupOvBytes + size LFPBI.reply/8)
   ifnot
      [
      pbi>>LFPBI.error.type = ec
      CompletePup(pbi, ptLookupFileError, pupOvBytes + size LFPBI.error/8)
      ]

if fd ne 0 then DestroyFD(fd)
lfs>>LFS.active = false
]