Commit a15bd319 authored by Huff, Israel's avatar Huff, Israel
Browse files

initial check-in of partial SFTP implementation

- need to finish implementation and separate into new source and header files
parent 3ba6bb1b
Pipeline #100041 failed with stages
in 6 minutes and 17 seconds
......@@ -3,7 +3,9 @@
#include "radixbug/bug.hh"
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <fcntl.h>
#include <cassert>
#include <sstream>
......@@ -115,6 +117,148 @@ QString Channel::readExecErr()
return QString("");
}
// ----------------------------------------------------------------------------
class SFTPSessionImpl
{
public:
sftp_session sftpSession = nullptr;
int errorCode = SSH_OK;
const char* errorMsg = nullptr;
explicit SFTPSessionImpl(ssh_session sshSession)
{
sftpSession = sftp_new(sshSession);
if (nullptr == sftpSession)
{
errorCode = SSH_ERROR;
errorMsg = ssh_get_error(sshSession);
return;
}
// SSH_OK, SSH_ERROR, etc; see libssh.h
int rc = sftp_init(sftpSession);
if (rc != SSH_OK)
{
errorCode = sftp_get_error(sftpSession);
sftp_free(sftpSession);
sftpSession = nullptr;
}
}
~SFTPSessionImpl()
{
if (sftpSession != nullptr) sftp_free(sftpSession);
}
}; // class SFTPSessionImpl
SFTPSession::SFTPSession()
{
radix_tagged_line("SFTPSession::SFTPSession()");
p = nullptr;
}
SFTPSession::~SFTPSession()
{
radix_tagged_line("SFTPSession::~SFTPSession()");
if (p != nullptr) delete p;
}
bool SFTPSession::mkdir(QString dirName)
{
// S_IRWXU: create dir with read/write/exec by owner only
int rc = sftp_mkdir(p->sftpSession, dirName.toStdString().c_str(), S_IRWXU);
if (rc != SSH_OK)
{
if (sftp_get_error(p->sftpSession) != SSH_FX_FILE_ALREADY_EXISTS)
{
p->errorCode = SSH_ERROR;
p->errorMsg = ssh_get_error(p->sftpSession);
return false;
}
}
return true;
}
bool SFTPSession::rmdir(QString dirName)
{
int rc = sftp_rmdir(p->sftpSession, dirName.toStdString().c_str());
if (rc != SSH_OK)
{
if (sftp_get_error(p->sftpSession) != SSH_FX_FILE_ALREADY_EXISTS)
{
p->errorCode = SSH_ERROR;
p->errorMsg = ssh_get_error(p->sftpSession);
return false;
}
}
return true;
}
SFTPFile SFTPSession::openFile(QString filename, int accessType)
{
return SFTPFile(*this, filename.toStdString().c_str(), accessType);
}
SFTPDir SFTPSession::openDir(QString dirName)
{
return SFTPDir(*this, dirName.toStdString().c_str());
}
QString SFTPSession::error() { return p->errorMsg; }
QString SFTPSession::canonicalize(QString path)
{
char* str =
sftp_canonicalize_path(p->sftpSession, path.toStdString().c_str());
if (nullptr == str) return "";
return QString(str);
}
// ----------------------------------------------------------------------------
class SFTPFileImpl
{
public:
sftp_file file = nullptr;
explicit SFTPFileImpl(sftp_session sftpSession, QString filename,
int accessType)
{
file = sftp_open(sftpSession, filename.toStdString().c_str(), accessType,
S_IRWXU);
}
~SFTPFileImpl()
{
if (file != nullptr) sftp_close(file);
}
}; // class SFTPFileImpl
SFTPFile::SFTPFile(SFTPSession& sftpSession, QString filename, int accessType)
{
p = new SFTPFileImpl(sftpSession.p->sftpSession, filename, accessType);
}
// ----------------------------------------------------------------------------
class SFTPDirImpl
{
public:
sftp_dir dir = nullptr;
explicit SFTPDirImpl(sftp_session sftpSession, QString dirName)
{
dir = sftp_opendir(sftpSession, dirName.toStdString().c_str());
}
~SFTPDirImpl()
{
if (dir != nullptr) sftp_closedir(dir);
}
}; // class SFTPDirImpl
SFTPDir::SFTPDir(SFTPSession sftpSession, QString dirName)
{
p = new SFTPDirImpl(sftpSession.p->sftpSession, dirName);
}
// ----------------------------------------------------------------------------
class SessionImpl
{
public:
......@@ -450,4 +594,13 @@ Channel Session::newChannel()
return channel;
}
SFTPSession Session::newSFTPSession()
{
assert_ssh_session(p->session,
"newSFTPSession() -- SSH Session is not allocated.");
SFTPSession sftpSession;
sftpSession.p = new SFTPSessionImpl(p->session);
return sftpSession;
}
} // namespace rsm
......@@ -70,6 +70,12 @@ enum class SessionHostState
class ChannelImpl;
class SessionImpl;
class Session;
class SFTPSessionImpl;
class SFTPSession;
class SFTPFileImpl;
class SFTPFile;
class SFTPDirImpl;
class SFTPDir;
class RSM_PUBLIC Channel
{
......@@ -297,6 +303,69 @@ class RSM_PUBLIC Session
*/
Channel newChannel();
}; // class SessionWorker
/**
* @brief newSFTPSession Allocates a new SFTP session from this SSH session
* @return
*/
SFTPSession newSFTPSession();
}; // class Session
// ----------------------------------------------------------------------------
class RSM_PUBLIC SFTPSession
{
protected:
// Private implementation
SFTPSessionImpl* p;
public:
SFTPSession();
~SFTPSession();
bool mkdir(QString dirName);
bool rmdir(QString dirName);
// int accessType = O_RDONLY | O_WRONLY | ...; see fcntl.h
SFTPFile openFile(QString fileName, int accessType);
SFTPDir openDir(QString dirName);
QString error();
QString canonicalize(QString path);
friend Session;
friend SFTPFile;
friend SFTPDir;
}; // class SFTPSession
// ----------------------------------------------------------------------------
class RSM_PUBLIC SFTPFile
{
private:
// Private implementation
SFTPFileImpl* p;
public:
SFTPFile(SFTPSession& sftpSession, QString filename, int accessType);
~SFTPFile();
bool isOpen();
size_t write(QString str);
QString read(size_t nBytes);
bool close();
size_t seek();
size_t tell();
}; // class SFTPFile
// ----------------------------------------------------------------------------
class RSM_PUBLIC SFTPDir
{
private:
// Private implementation
SFTPDirImpl* p;
public:
SFTPDir(SFTPSession sftpSession, QString dirName);
~SFTPDir();
bool hasNext();
// sftp_attributes_struct next();
bool close();
}; // class SFTPDir
} // namespace rsm
#endif /* RSM_RSMCORE_SESSION_HH_*/
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment