Add emulation of /dev/zero for network testing

This commit is contained in:
Michael Theall 2020-05-24 21:21:19 -05:00
parent ab5051082c
commit 70d59218cd
3 changed files with 67 additions and 31 deletions

View File

@ -316,6 +316,9 @@ private:
/// \brief Whether MLST unix.mode fact is enabled /// \brief Whether MLST unix.mode fact is enabled
bool m_mlstUnixMode : 1; bool m_mlstUnixMode : 1;
/// \brief Whether emulating /dev/zero
bool m_devZero : 1;
/// \brief Abort a transfer /// \brief Abort a transfer
/// \param args_ Command arguments /// \param args_ Command arguments
void ABOR (char const *args_); void ABOR (char const *args_);

View File

@ -203,9 +203,23 @@ bool fs::File::readAll (void *const buffer_, std::size_t const size_)
std::make_signed_t<std::size_t> fs::File::write (void const *const buffer_, std::size_t const size_) std::make_signed_t<std::size_t> fs::File::write (void const *const buffer_, std::size_t const size_)
{ {
assert (buffer_);
assert (size_ > 0);
return std::fwrite (buffer_, 1, size_, m_fp.get ()); return std::fwrite (buffer_, 1, size_, m_fp.get ());
} }
std::make_signed_t<std::size_t> fs::File::write (IOBuffer &buffer_)
{
assert (buffer_.usedSize () > 0);
auto const rc = write (buffer_.usedArea (), buffer_.usedSize ());
if (rc > 0)
buffer_.markFree (rc);
return rc;
}
bool fs::File::writeAll (void const *const buffer_, std::size_t const size_) bool fs::File::writeAll (void const *const buffer_, std::size_t const size_)
{ {
assert (buffer_); assert (buffer_);

View File

@ -279,7 +279,8 @@ FtpSession::FtpSession (FtpConfig &config_, UniqueSocket commandSocket_)
m_mlstSize (true), m_mlstSize (true),
m_mlstModify (true), m_mlstModify (true),
m_mlstPerm (true), m_mlstPerm (true),
m_mlstUnixMode (false) m_mlstUnixMode (false),
m_devZero (false)
{ {
if (m_config.user ().empty ()) if (m_config.user ().empty ())
m_authorizedUser = true; m_authorizedUser = true;
@ -612,6 +613,7 @@ void FtpSession::setState (State const state_, bool const closePasv_, bool const
m_workItem.clear (); m_workItem.clear ();
} }
m_devZero = false;
m_file.close (); m_file.close ();
m_dir.close (); m_dir.close ();
} }
@ -1055,7 +1057,11 @@ void FtpSession::xferFile (char const *const args_, XferFileMode const mode_)
return; return;
} }
if (mode_ == XferFileMode::RETR) if (path == "/devZero")
{
m_devZero = true;
}
else if (mode_ == XferFileMode::RETR)
{ {
// stat the file // stat the file
struct stat st; struct stat st;
@ -1709,29 +1715,34 @@ bool FtpSession::retrieveTransfer ()
{ {
m_xferBuffer.clear (); m_xferBuffer.clear ();
auto const buffer = m_xferBuffer.freeArea (); if (!m_devZero)
auto const size = m_xferBuffer.freeSize ();
// we have sent all the data, so read some more
auto const rc = m_file.read (buffer, size);
if (rc < 0)
{ {
// failed to read data // we have sent all the data, so read some more
sendResponse ("451 %s\r\n", std::strerror (errno)); auto const rc = m_file.read (m_xferBuffer);
setState (State::COMMAND, true, true); if (rc < 0)
return false; {
} // failed to read data
sendResponse ("451 %s\r\n", std::strerror (errno));
setState (State::COMMAND, true, true);
return false;
}
if (rc == 0) if (rc == 0)
{
// reached end of file
sendResponse ("226 OK\r\n");
setState (State::COMMAND, true, true);
return false;
}
}
else
{ {
// reached end of file auto const buffer = m_xferBuffer.freeArea ();
sendResponse ("226 OK\r\n"); auto const size = m_xferBuffer.freeSize ();
setState (State::COMMAND, true, true);
return false;
}
// we read some data std::memset (buffer, 0, size);
m_xferBuffer.markUsed (rc); m_xferBuffer.markUsed (size);
}
} }
// send any pending data // send any pending data
@ -1780,19 +1791,27 @@ bool FtpSession::storeTransfer ()
} }
} }
// write any pending data if (!m_devZero)
auto const rc = m_file.write (m_xferBuffer.usedArea (), m_xferBuffer.usedSize ());
if (rc <= 0)
{ {
// error writing data // write any pending data
sendResponse ("426 %s\r\n", rc < 0 ? std::strerror (errno) : "Failed to write data"); auto const rc = m_file.write (m_xferBuffer);
setState (State::COMMAND, true, true); if (rc <= 0)
return false; {
// error writing data
sendResponse ("426 %s\r\n", rc < 0 ? std::strerror (errno) : "Failed to write data");
setState (State::COMMAND, true, true);
return false;
}
// we can try to recv/write more data
LOCKED (m_filePosition += rc);
}
else
{
LOCKED (m_filePosition += m_xferBuffer.usedSize ());
m_xferBuffer.clear ();
} }
// we can try to recv/write more data
LOCKED (m_filePosition += rc);
m_xferBuffer.markFree (rc);
return true; return true;
} }