Get a directory listing filtered by search criteria

Return TypeFunction nameArguments
hzEcodehzFtpClient::GetDirList(hzVect<hzDirent>&,hzString&,)

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

Function Logic:

0:START 1:unknown 2:unknown 3:items items rc 4:unknown 5:rc 6:unknown 7:items 8:unknown 9:items 10:items 11:len 12:unknown 13:items 14:unknown 15:items 16:unknown 17:items items rc 18:nTotal items 19:unknown 20:rc 21:unknown 22:items 23:unknown 24:nTotal m_x_rbuf items 25:items 26:unknown 27:unknown 28:unknown 29:items 30:items 31:unknown 32:items 33:unknown 34:items rc 35:unknown 36:unknown 37:Return rc 38:j 39:unknown 40:unknown 41:unknown 42:* j rc 43:unknown 44:rc 45:unknown 46:* 47:m_nTries 48:Return rc 49:items 50:Return rc

Function body:

hzEcode hzFtpClient::GetDirList (hzVect<hzDirent>& listing)hzString& Criteria, 
{
   //  Get a directory listing filtered by search criteria
   //  
   //  Arguments: 1) listing  The vector of directory entries populated by this operation
   //     2) Criteria The file/directory search criteria
   //  
   //  Returns: E_HOSTFAIL If there was a communication failure and reconnect failed
   //     E_PROTOCOL If the server did not provide a listing
   //     E_OK  If the directory listing was recieved
   _hzfunc("hzFtpClient::GetDirList") ;
   hzTcpClient     X ;             //  Temporary data connection
   hzDirent        meta ;          //  Metafile
   hzChain         Listing ;       //  Temporary store for listing
   hzChain::Iter   z ;             //  For processing naked listing
   hzString        filename ;      //  Name of file
   uint32_t        nRecv ;         //  Bytes recieved this packet
   uint32_t        nTotal ;        //  Total bytes recieved
   uint32_t        len ;           //  Length of content to send
   uint32_t        nTry ;          //  Reconnections
   uint32_t        nTryData ;      //  Timeouts on the data channel
   char*           j ;             //  For loading line buffer
   char            cvLine [300];//  Line buffer
   hzEcode         rc = E_OK ;     //  Return code
   /*
   **  ** Loop round until success
   **      */
   //  X.SetDebug(_hzGlobal_Debug & HZ_DEBUG_CLIENT) ;
   for (nTry = 0; nTry < 2; nTry++)
   {
       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 .. aborting\n") ;
           continue ;
       }
       //  Send the LIST command
       if (Criteria)
           sprintf(m_c_sbuf, "LIST %s\r\n", *Criteria) ;
       else
           sprintf(m_c_sbuf, "LIST\r\n") ;
       len = strlen(m_c_sbuf) ;
       if ((rc = m_ConnControl.Send(m_c_sbuf, len)) != E_OK)
       {
           threadLog("Could not send LIST command\n") ;
           continue ;
       }
       //  Get the expected 150 in the control client
       if ((rc = _ftprecv(nRecv, *_fn)) != E_OK)
       {
           threadLog("Did not recieve a response to LIST command\n") ;
           continue ;
       }
       if (m_nRescode != 150)
       {
           threadLog("Expected code of 150 but got %d. Aborting\n", m_nRescode) ;
           _logrescode() ;
           rc = E_PROTOCOL ;
           break ;
       }
       //  Get the listing in the data client
       nTotal = 0;
       Listing.Clear() ;
       for (nTryData = 0; nTryData < 3;)
       {
           rc = X.Recv(m_x_rbuf, nRecv, HZ_MAXPACKET) ;
           if (rc != E_OK)
           {
               threadLog("LIST: Read failed (total so far %d bytes)\n", nTotal) ;
               break ;
           }
           if (!nRecv)
               break ;
           nTotal += nRecv ;
           m_x_rbuf[nRecv] = 0;
           Listing << m_x_rbuf ;
       }
       X.Close() ;
       //  Unless the transfer is a complete success, do a reconnect.
       if (rc == E_TIMEOUT || nTryData == 3)
           continue ;
       if (rc == E_RECVFAIL)
           continue ;
       if (Listing.Size())
           threadLog("LIST: Total listing %d bytes\n", nTotal) ;
       else
           threadLog("LIST: Empty list. No files\n") ;
       //  If a list has been sent there will be a 226 sent by the server which we will need to read - if only to get rid of it before we move on.
       if ((rc = _ftprecv(nRecv, *_fn)) != E_OK)
       {
           threadLog("Did not recieve a response to LIST command\n") ;
           continue ;
       }
       if (m_nRescode != 226)
       {
           threadLog("LIST: Expected code of 226 (Xfer complete) but got %d. Aborting\n", m_nRescode) ;
           rc = E_PROTOCOL ;
       }
       //  No further communication required so drop out
       break ;
   }
   if (rc == E_OK)
   {
       //  Examine the dir listing (if there is one)
       if (!Listing.Size())
           return rc ;
       j = cvLine ;
       for (z = Listing ; !z.eof() ; z++)
       {
           if (*z == CHAR_CR)
               continue ;
           if (*z == CHAR_NL)
           {
               //  Process the line
               *j = 0;
               j = cvLine ;
               //  Set meta data for the file
               rc = _setmetafile(meta, cvLine) ;
               if (rc != E_OK)
                   break ;
               //  Add the meta data
               rc = listing.Add(meta) ;
               if (rc != E_OK)
                   break ;
               continue ;
           }
           *j++ = *z ;
       }
       m_nTries = 0;
       return rc ;
   }
   threadLog("Could not get directory listing\n\n") ;
   return rc ;
}