** 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 ; }