SSH: Add SFTP operations needed to implement remote FS traversal.

Change-Id: I3e7b52513211959a976545667e8e8372f2001c7e
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Christian Kandeler
2012-02-01 17:39:52 +01:00
committed by hjk
parent 778108ebd0
commit 7c0abc29cd
11 changed files with 275 additions and 18 deletions

View File

@@ -46,7 +46,11 @@ SftpTest::SftpTest(const Parameters &params)
: m_parameters(params), m_state(Inactive), m_error(false),
m_bigFileUploadJob(SftpInvalidJob),
m_bigFileDownloadJob(SftpInvalidJob),
m_bigFileRemovalJob(SftpInvalidJob)
m_bigFileRemovalJob(SftpInvalidJob),
m_mkdirJob(SftpInvalidJob),
m_statDirJob(SftpInvalidJob),
m_lsDirJob(SftpInvalidJob),
m_rmDirJob(SftpInvalidJob)
{
}
@@ -85,6 +89,9 @@ void SftpTest::handleConnected()
SLOT(handleChannelInitializationFailure(QString)));
connect(m_channel.data(), SIGNAL(finished(Utils::SftpJobId, QString)),
this, SLOT(handleJobFinished(Utils::SftpJobId, QString)));
connect(m_channel.data(),
SIGNAL(fileInfoAvailable(Utils::SftpJobId, QList<Utils::SftpFileInfo>)),
SLOT(handleFileInfo(Utils::SftpJobId, QList<Utils::SftpFileInfo>)));
connect(m_channel.data(), SIGNAL(closed()), this,
SLOT(handleChannelClosed()));
m_state = InitializingChannel;
@@ -107,14 +114,16 @@ void SftpTest::handleDisconnected()
else
std::cout << "No errors encountered.";
std::cout << std::endl;
qApp->quit();
qApp->exit(m_error ? EXIT_FAILURE : EXIT_SUCCESS);
}
void SftpTest::handleError()
{
std::cerr << "Encountered SSH error: "
<< qPrintable(m_connection->errorString()) << "." << std::endl;
qApp->quit();
m_error = true;
m_state = Disconnecting;
qApp->exit(EXIT_FAILURE);
}
void SftpTest::handleChannelInitialized()
@@ -384,17 +393,84 @@ void SftpTest::handleJobFinished(Utils::SftpJobId job, const QString &error)
m_state = RemovingBig;
break;
}
case RemovingBig: {
case RemovingBig:
if (!handleBigJobFinished(job, m_bigFileRemovalJob, error, "removing"))
return;
const QString remoteFp
= remoteFilePath(QFileInfo(m_localBigFile->fileName()).fileName());
std::cout << "Big files successfully removed. "
<< "Now closing the SFTP channel..." << std::endl;
<< "Now creating remote directory..." << std::endl;
m_remoteDirPath = QLatin1String("/tmp/sftptest-") + QDateTime::currentDateTime().toString();
m_mkdirJob = m_channel->createDirectory(m_remoteDirPath);
m_state = CreatingDir;
break;
case CreatingDir:
if (!handleJobFinished(job, m_mkdirJob, error, "creating remote directory"))
return;
std::cout << "Directory successfully created. Now checking directory attributes..."
<< std::endl;
m_statDirJob = m_channel->statFile(m_remoteDirPath);
m_state = CheckingDirAttributes;
break;
case CheckingDirAttributes: {
if (!handleJobFinished(job, m_statDirJob, error, "checking directory attributes"))
return;
if (m_dirInfo.type != FileTypeDirectory) {
std::cerr << "Error: Newly created directory has file type " << m_dirInfo.type
<< ", expected was " << FileTypeDirectory << "." << std::endl;
earlyDisconnectFromHost();
return;
}
const QString fileName = QFileInfo(m_remoteDirPath).fileName();
if (m_dirInfo.name != fileName) {
std::cerr << "Error: Remote directory reports file name '"
<< qPrintable(m_dirInfo.name) << "', expected '" << qPrintable(fileName) << "'."
<< std::endl;
earlyDisconnectFromHost();
return;
}
std::cout << "Directory attributes ok. Now checking directory contents..." << std::endl;
m_lsDirJob = m_channel->listDirectory(m_remoteDirPath);
m_state = CheckingDirContents;
break;
}
case CheckingDirContents:
if (!handleJobFinished(job, m_lsDirJob, error, "checking directory contents"))
return;
if (m_dirContents.count() != 2) {
std::cerr << "Error: Remote directory has " << m_dirContents.count()
<< " entries, expected 2." << std::endl;
earlyDisconnectFromHost();
return;
}
foreach (const SftpFileInfo &fi, m_dirContents) {
if (fi.type != FileTypeDirectory) {
std::cerr << "Error: Remote directory has entry of type " << fi.type
<< ", expected " << FileTypeDirectory << "." << std::endl;
earlyDisconnectFromHost();
return;
}
if (fi.name != QLatin1String(".") && fi.name != QLatin1String("..")) {
std::cerr << "Error: Remote directory has entry '" << qPrintable(fi.name)
<< "', expected '.' or '..'." << std::endl;
earlyDisconnectFromHost();
return;
}
}
if (m_dirContents.first().name == m_dirContents.last().name) {
std::cerr << "Error: Remote directory has two entries of the same name." << std::endl;
earlyDisconnectFromHost();
return;
}
std::cout << "Directory contents ok. Now removing directory..." << std::endl;
m_rmDirJob = m_channel->removeDirectory(m_remoteDirPath);
m_state = RemovingDir;
break;
case RemovingDir:
if (!handleJobFinished(job, m_rmDirJob, error, "removing directory"))
return;
std::cout << "Directory successfully removed. Now closing the SFTP channel..." << std::endl;
m_state = ChannelClosing;
m_channel->closeChannel();
break;
}
case Disconnecting:
break;
default:
@@ -406,6 +482,32 @@ void SftpTest::handleJobFinished(Utils::SftpJobId job, const QString &error)
}
}
void SftpTest::handleFileInfo(SftpJobId job, const QList<SftpFileInfo> &fileInfoList)
{
switch (m_state) {
case CheckingDirAttributes: {
static int count = 0;
if (!checkJobId(job, m_statDirJob, "checking directory attributes"))
return;
if (++count > 1) {
std::cerr << "Error: More than one reply for directory attributes check." << std::endl;
earlyDisconnectFromHost();
return;
}
m_dirInfo = fileInfoList.first();
break;
}
case CheckingDirContents:
if (!checkJobId(job, m_lsDirJob, "checking directory contents"))
return;
m_dirContents << fileInfoList;
break;
default:
std::cerr << "Error: Unexpected file info in state " << m_state << "." << std::endl;
earlyDisconnectFromHost();
}
}
void SftpTest::removeFile(const FilePtr &file, bool remoteToo)
{
if (!file)
@@ -438,6 +540,17 @@ void SftpTest::earlyDisconnectFromHost()
m_connection->disconnectFromHost();
}
bool SftpTest::checkJobId(SftpJobId job, SftpJobId expectedJob, const char *activity)
{
if (job != expectedJob) {
std::cerr << "Error " << activity << ": Expected job id " << expectedJob
<< ", got job id " << job << '.' << std::endl;
earlyDisconnectFromHost();
return false;
}
return true;
}
void SftpTest::removeFiles(bool remoteToo)
{
foreach (const FilePtr &file, m_localSmallFiles)
@@ -465,6 +578,19 @@ bool SftpTest::handleJobFinished(SftpJobId job, JobMap &jobMap,
return true;
}
bool SftpTest::handleJobFinished(SftpJobId job, SftpJobId expectedJob, const QString &error,
const char *activity)
{
if (!checkJobId(job, expectedJob, activity))
return false;
if (!error.isEmpty()) {
std::cerr << "Error " << activity << ": " << qPrintable(error) << "." << std::endl;
earlyDisconnectFromHost();
return false;
}
return true;
}
bool SftpTest::handleBigJobFinished(SftpJobId job, SftpJobId expectedJob,
const QString &error, const char *activity)
{