** Rename the file to the target name, set mtime of the local file to match that of the server
| Return Type | Function name | Arguments |
|---|---|---|
| hzEcode | hzFtpClient::FileDownload | (hzDirent&,) |
Declared in file: hzFtpClient.h
Defined in file : hzFtpClient.cpp
Function Logic:
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 ;
}