** Rename the file to the target name, set mtime of the local file to match that of the server

Return TypeFunction nameArguments
hzEcodehzFtpClient::FileDownload(hzDirent&,)

Declared in file: hzFtpClient.h
Defined in file : hzFtpClient.cpp

Function Logic:

0:START 1:hzDirent::Size 2:!finfo.Size() 3:Return E_OK 4:tmpFile hzDirent::strName tmpFile tmpFile hzDirent::strName tgtFile nTry 5:nTry<2; 6:start 7:nTotal 8:nTry==1 9:hzTcpClient::Close hzTcpClient::Close hzFtpClient::_reconnect rc 10:rc!=E_OK 11:hzFtpClient::_openpasv rc 12:rc!=E_OK 13:hzDirent::txtName sprintf strlen len 14:(rc=m_ConnControl.Send(m_c_sbuf,len))!=E_OK 15:hzDirent::txtName 16:(rc=_ftprecv(nRecv,*_fn))!=E_OK 17:hzDirent::txtName 18:m_nRescode>=400 19:rc 20:ofstream::open ofstream::fail 21:os.fail() 22:rc 23:nTotal 24:hzTcpClient::Recv rc 25:rc!=E_OK 26:hzDirent::txtName hzTcpClient::Close close ofstream::clear 27:Goto start 28:!nRecv 29:nTotal ofstream::write ofstream::fail 30:os.fail() 31:hzDirent::txtName rc 32:hzTcpClient::Close close 33:rc==E_WRITEFAIL 34:hzDirent::Size hzDirent::txtName 35:rc==E_OK 36:rename hzDirent::Size hzDirent::txtName hzDirent::Mtime epoch time svr_mtime svr_mtime hzDirent::txtName utime 37:(rc=_ftprecv(nRecv,*_fn))!=E_OK 38:hzDirent::txtName hzFtpClient::_reconnect rc 39:m_nRescode!=226 40:m_nRescode>=400 41:rc 42:rc!=E_OK 43:hzDirent::txtName 44:hzDirent::txtName m_nTries 45:Return rc

Function body:

hzEcode hzFtpClient::FileDownload (hzDirent& finfo)
{
   _hzfunc("hzFtpClient::FileDownload") ;
   struct utimbuf  svr_mtime ;
   std::ofstream   os ;
   hzTcpClient     X ;
   hzString        tmpFile ;
   hzString        tgtFile ;
   uint32_t        epoch ;
   uint32_t        nRecv ;
   uint32_t        nTotal = 0;
   uint32_t        len ;
   uint32_t        nTry ;
   hzEcode         rc ;
   if (!finfo.Size())
       return E_OK ;
   tmpFile = m_LocalDir + "/" ;
   tmpFile += finfo.strName() ;
   tmpFile += ".tmp" ;
   tgtFile = m_LocalDir + "/" + finfo.strName() ;
   /*
   **  ** Loop round until success
   **      */
   for (nTry = 0; nTry < 2; nTry++)
   {
start:
       nTotal = 0;
       if (nTry == 1)
       {
           X.Close() ;
           m_ConnControl.Close() ;
           rc = _reconnect() ;
           if (rc != E_OK)
               break ;
       }
       /*
       **  ** First step is to open a data channel
       **           */
       rc = _openpasv(X) ;
       if (rc != E_OK)
       {
           threadLog("Failed PASV\n") ;
           continue ;
       }
       /*
       **  ** Send the RETR command and recv response
       **           */
       sprintf(m_c_sbuf, "RETR %s\r\n", finfo.txtName()) ;
       len = strlen(m_c_sbuf) ;
       if ((rc = m_ConnControl.Send(m_c_sbuf, len)) != E_OK)
       {
           threadLog("Could not send RETR command to get file %s\n", finfo.txtName()) ;
           continue ;
       }
       if ((rc = _ftprecv(nRecv, *_fn)) != E_OK)
       {
           threadLog("Could not get RETR respeonse (file=%s)\n", finfo.txtName()) ;
           continue ;
       }
       /*
       **  ** Check response code
       **           */
       if (m_nRescode >&eq; 400)
       {
           threadLog("Got bad response to RETR (%d)\n", m_nRescode) ;
           rc = E_PROTOCOL ;
           break ;
       }
       /*
       **  ** Then if all is well, download the file
       **           */
       os.open(*tmpFile) ;
       if (os.fail())
       {
           threadLog("Failed to open download temp file %s\n", *tmpFile) ;
           rc = E_OPENFAIL ;
           break ;
       }
       for (nTotal = 0; nTotal < finfo.Size() ;)
       {
           rc = X.Recv(m_x_rbuf, nRecv, HZ_MAXPACKET) ;
           if (rc != E_OK)
           {
               threadLog("Socket error during download of file %s\n", finfo.txtName()) ;
               X.Close() ;
               os.close() ;
               os.clear() ;
               goto start ;
           }
           if (!nRecv)
               break ;
           nTotal += nRecv ;
           os.write(m_x_rbuf, nRecv) ;
           if (os.fail())
           {
               threadLog("Failed to write data to the target file %s\n", finfo.txtName()) ;
               rc = E_WRITEFAIL ;
               break ;
           }
       }
       X.Close() ;
       os.close() ;
       if (rc == E_WRITEFAIL)
       {
           threadLog("Aborted operation to download %d of %d bytes to the target file %s - No disk space\n", nTotal, finfo.Size(), finfo.txtName()) ;
       }
       break ;
   }
   if (rc == E_OK)
   {
       /*
       **  ** Rename the file to the target name, set mtime of the local file to match that of the server
       **           */
       rename(*tmpFile, *tgtFile) ;
       threadLog("Downloaded %d of %d bytes to the target file %s\n", nTotal, finfo.Size(), finfo.txtName()) ;
       epoch = finfo.Mtime() ;
       svr_mtime.actime = time(0);
       svr_mtime.modtime = epoch ;
       utime(finfo.txtName(), &svr_mtime) ;
       /*
       **  ** Get server progress report of download. If broken pipe reconnect but as we have the file already we don't
       **    ** have to repeat any steps.
       **           */
       if ((rc = _ftprecv(nRecv, *_fn)) != E_OK)
       {
           threadLog("Could not get response to RETR command (file=%s)\n", finfo.txtName()) ;
           rc = _reconnect() ;
       }
       else
       {
           if (m_nRescode != 226)
               threadLog("Expected code of 226 (Xfer complete), got %d\n", m_nRescode) ;
           if (m_nRescode >&eq; 400)
               rc = E_RECVFAIL ;
       }
   }
   if (rc != E_OK)
       threadLog("Could not download %s\n\n", finfo.txtName()) ;
   else
   {
       threadLog("Downloaded %s\n", finfo.txtName()) ;
       m_nTries = 0;
   }
   return rc ;
}