Get a directory listing filtered by search criteria
| Return Type | Function name | Arguments |
|---|---|---|
| hzEcode | hzFtpClient::GetDirList | (hzVect<hzDirent>&,hzString&,) |
Declared in file: hzFtpClient.h
Defined in file : hzFtpClient.cpp
Function Logic:
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 ;
}