mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
SFtp: GetInfo() method re-added. Pick semantics improved & cosmetics.
git-svn-id: svn://ultimatepp.org/upp/trunk@12158 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
1f72504a1a
commit
f50acb57aa
6 changed files with 83 additions and 73 deletions
|
|
@ -47,10 +47,10 @@ String GetName(int type, int64 id)
|
|||
void Ssh::Check()
|
||||
{
|
||||
auto sock = ssh->socket;
|
||||
|
||||
|
||||
if(IsTimeout())
|
||||
SetError(-1, "Operation timed out.");
|
||||
|
||||
|
||||
if(ssh->status == ABORTED || (sock && ssh->socket->IsAbort()))
|
||||
SetError(-1, "Operation aborted.");
|
||||
|
||||
|
|
@ -63,10 +63,10 @@ bool Ssh::Run(Gate<>&& fn)
|
|||
try {
|
||||
if(InProgress())
|
||||
SetError(-1, "An operation is already in progress.");
|
||||
|
||||
|
||||
ssh->status = WORKING;
|
||||
ssh->start_time = msecs();
|
||||
|
||||
|
||||
|
||||
while(InProgress()) {
|
||||
Mutex::Lock __m(StaticMutex);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class Ssh {
|
|||
public:
|
||||
void Abort() { if(ssh) ssh->status = ABORTED; }
|
||||
int GetTimeout() const { return ssh->timeout; }
|
||||
int GetWaitStep() const { return ssh->waitstep; }
|
||||
int GetWaitStep() const { return ssh->waitstep; }
|
||||
bool InProgress() const { return ssh->status == WORKING; }
|
||||
bool IsError() const { return ssh->status == FAILED || ssh->status == ABORTED; }
|
||||
int GetError() const { return ssh->error.Get<int>(); }
|
||||
|
|
@ -12,7 +12,7 @@ public:
|
|||
template <class T> T& To() { auto* t = dynamic_cast<T*>(this); ASSERT(t); return *t; }
|
||||
template <class T> bool Is() const { return dynamic_cast<const T*>(this); }
|
||||
|
||||
operator bool() { return ssh; }
|
||||
operator bool() const { return ssh; }
|
||||
|
||||
static void Trace(bool b = true) { SSH::sTrace = b; }
|
||||
static void TraceVerbose(int level) { Trace((bool)level); SSH::sTraceVerbose = level; }
|
||||
|
|
@ -45,7 +45,7 @@ protected:
|
|||
int waitstep;
|
||||
int chunk_size;
|
||||
int status;
|
||||
bool noloop;
|
||||
bool noloop;
|
||||
};
|
||||
One<CoreData> ssh;
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ protected:
|
|||
bool Run(Gate<>&& fn);
|
||||
bool WouldBlock(int rc) { return rc == LIBSSH2_ERROR_EAGAIN; }
|
||||
bool WouldBlock() { return ssh->session && WouldBlock(libssh2_session_last_errno(ssh->session)); }
|
||||
bool IsTimeout() const { return ssh->timeout > 0 && msecs(ssh->start_time) >= ssh->timeout; }
|
||||
bool IsTimeout() const { return !IsNull(ssh->timeout) && ssh->timeout > 0 && msecs(ssh->start_time) >= ssh->timeout; }
|
||||
void SetError(int rc, const String& reason = Null);
|
||||
|
||||
void AddTo(SocketWaitEvent& e) { e.Add(*ssh->socket, GetWaitEvents()); }
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ History:
|
|||
--------------------
|
||||
2018-08-10: SSH package: Third iteration.
|
||||
SSH package is now officially a part of Ultimate++.
|
||||
Full non-blocking mode and MT convenience methods removed in favor of simple an robust interface.
|
||||
Full non-blocking mode and MT convenience methods removed in favor of simple an robust blocking interface.
|
||||
Ssh, SFtp and SshSession classes are refactored accordingly.
|
||||
SFtpStream variants are added to the package (Thanks Mirek!).
|
||||
Memory footprint slightly reduced.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ void SFtp::Exit()
|
|||
{
|
||||
if(!sftp_session)
|
||||
return;
|
||||
|
||||
|
||||
Run([=]() mutable {
|
||||
if(WouldBlock(libssh2_sftp_shutdown(*sftp_session)))
|
||||
return false;
|
||||
|
|
@ -49,7 +49,7 @@ int SFtp::LStat(const String& path, SFtpAttrs& a, int type)
|
|||
SFtpHandle SFtp::Open(const String& path, dword flags, long mode)
|
||||
{
|
||||
SFtpHandle h = nullptr;
|
||||
|
||||
|
||||
Run([=, &h] () mutable {
|
||||
h = libssh2_sftp_open(*sftp_session, path, flags, mode);
|
||||
if(!h && !WouldBlock())
|
||||
|
|
@ -58,7 +58,7 @@ SFtpHandle SFtp::Open(const String& path, dword flags, long mode)
|
|||
LLOG(Format("File '%s' is successfully opened.", path));
|
||||
return h;
|
||||
});
|
||||
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ SFtp& SFtp::Seek(SFtpHandle handle, int64 position)
|
|||
int64 SFtp::GetPos(SFtpHandle handle)
|
||||
{
|
||||
int64 pos = 0;
|
||||
|
||||
|
||||
return Run([=, &pos] () mutable {
|
||||
pos = libssh2_sftp_tell64(handle);
|
||||
LLOG("File position: " << pos);
|
||||
|
|
@ -131,9 +131,10 @@ int64 SFtp::GetPos(SFtpHandle handle)
|
|||
});
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool SFtp::Read(SFtpHandle handle, Event<const void*, int>&& consumer, int size, int& done)
|
||||
{
|
||||
int sz = min(size, ssh->chunk_size);
|
||||
int sz = min(size - done, ssh->chunk_size);
|
||||
Buffer<char> buffer(sz);
|
||||
|
||||
int rc = libssh2_sftp_read(handle, buffer, sz);
|
||||
|
|
@ -146,15 +147,18 @@ bool SFtp::Read(SFtpHandle handle, Event<const void*, int>&& consumer, int size,
|
|||
SetError(-1, "Read aborted.");
|
||||
ssh->start_time = msecs();
|
||||
}
|
||||
if(!rc)
|
||||
|
||||
auto b = !rc || done == size;
|
||||
|
||||
if(b)
|
||||
LLOG("EOF received.");
|
||||
return rc == 0 || done == size;
|
||||
return b;
|
||||
}
|
||||
|
||||
bool SFtp::Write(SFtpHandle handle, const void* buffer, int size, int& done)
|
||||
{
|
||||
int sz = min(size - done, ssh->chunk_size);
|
||||
|
||||
|
||||
int rc = libssh2_sftp_write(handle, (const char*) buffer + done, sz);
|
||||
if(!WouldBlock(rc) && rc < 0)
|
||||
SetError(rc);
|
||||
|
|
@ -164,16 +168,18 @@ bool SFtp::Write(SFtpHandle handle, const void* buffer, int size, int& done)
|
|||
SetError(-1, "Write aborted.");
|
||||
ssh->start_time = msecs();
|
||||
}
|
||||
if(done == size)
|
||||
LLOG("EOF");
|
||||
return rc == 0 || done == size;
|
||||
auto b = !rc || done == size;
|
||||
|
||||
if(b)
|
||||
LLOG("EOF received.");
|
||||
return b;
|
||||
}
|
||||
|
||||
int SFtp::Get(SFtpHandle handle, void *ptr, int size)
|
||||
{
|
||||
int done = 0;
|
||||
|
||||
Run([=, &done]{
|
||||
|
||||
Run([=, &done]() mutable {
|
||||
return Read(
|
||||
handle,
|
||||
[=, &done](const void* p, int sz) {
|
||||
|
|
@ -191,7 +197,7 @@ bool SFtp::Put(SFtpHandle handle, const void *ptr, int size)
|
|||
{
|
||||
int done = 0;
|
||||
|
||||
Run([=, &done]{
|
||||
Run([=, &done]() mutable {
|
||||
return Write(handle, (char*) ptr, size, done);
|
||||
});
|
||||
|
||||
|
|
@ -225,7 +231,7 @@ void SFtp::LoadFile(Stream& out, const char *path)
|
|||
SFtpHandle SFtp::OpenDir(const String& path)
|
||||
{
|
||||
SFtpHandle h = nullptr;
|
||||
|
||||
|
||||
Run([=, &h] () mutable {
|
||||
h = libssh2_sftp_opendir(*sftp_session, path);
|
||||
if(!h && !WouldBlock())
|
||||
|
|
@ -273,7 +279,7 @@ bool SFtp::ListDir(SFtpHandle handle, DirList& list)
|
|||
|
||||
do {
|
||||
Zero(attrs);
|
||||
|
||||
|
||||
rc = libssh2_sftp_readdir_ex(
|
||||
handle,
|
||||
label, sizeof(label),
|
||||
|
|
@ -297,7 +303,7 @@ bool SFtp::ListDir(SFtpHandle handle, DirList& list)
|
|||
while(rc > 0);
|
||||
LLOG(Format("Directory listing is successful. (%d entries)", list.GetCount()));
|
||||
return true;
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -310,7 +316,7 @@ bool SFtp::ListDir(const String& path, DirList& list)
|
|||
bool SFtp::SymLink(const String& path, String* target, int type)
|
||||
{
|
||||
Buffer<char> buffer(512);
|
||||
|
||||
|
||||
if(type == LIBSSH2_SFTP_SYMLINK)
|
||||
return Run([=, &buffer] () mutable {
|
||||
int rc = libssh2_sftp_symlink_ex(
|
||||
|
|
@ -349,6 +355,19 @@ bool SFtp::SymLink(const String& path, String* target, int type)
|
|||
});
|
||||
}
|
||||
|
||||
SFtp::DirEntry SFtp::GetInfo(const String& path)
|
||||
{
|
||||
DirEntry finfo;
|
||||
|
||||
if(!GetAttrs(path, *finfo))
|
||||
return pick(Null);
|
||||
|
||||
finfo.filename = path;
|
||||
finfo.valid = true;
|
||||
|
||||
return pick(finfo);
|
||||
}
|
||||
|
||||
bool SFtp::GetAttrs(SFtpHandle handle, SFtpAttrs& attrs)
|
||||
{
|
||||
return Run([=, &attrs] () mutable {
|
||||
|
|
@ -393,12 +412,10 @@ Value SFtp::QueryAttr(const String& path, int attr)
|
|||
{
|
||||
DirEntry finfo;
|
||||
Value v;
|
||||
|
||||
|
||||
if(!GetAttrs(path, *finfo))
|
||||
return Null;
|
||||
|
||||
finfo.filename = path;
|
||||
|
||||
switch(attr) {
|
||||
case SFTP_ATTR_FILE:
|
||||
v = finfo.IsFile();
|
||||
|
|
@ -430,11 +447,6 @@ Value SFtp::QueryAttr(const String& path, int attr)
|
|||
case SFTP_ATTR_LAST_ACCESSED:
|
||||
v = finfo.GetLastAccessed();
|
||||
break;
|
||||
case SFTP_ATTR_INFO:
|
||||
finfo.valid = true;
|
||||
v = RawPickToValue(pick(finfo));
|
||||
finfo = Null;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -449,7 +461,7 @@ bool SFtp::ModifyAttr(const String& path, int attr, const Value& v)
|
|||
return false;
|
||||
|
||||
SFtpAttrs& attrs = *finfo;
|
||||
|
||||
|
||||
switch(attr) {
|
||||
case SFTP_ATTR_SIZE:
|
||||
attrs.flags |= LIBSSH2_SFTP_ATTR_SIZE;
|
||||
|
|
@ -466,7 +478,7 @@ bool SFtp::ModifyAttr(const String& path, int attr, const Value& v)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return SetAttrs(path, ~finfo);;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ public:
|
|||
DirEntry() { Zero(); }
|
||||
DirEntry(const Nuller&) { Zero(); }
|
||||
|
||||
DirEntry(DirEntry&& e) = default;
|
||||
DirEntry& operator=(DirEntry&& e) = default;
|
||||
DirEntry(DirEntry&&) = default;
|
||||
DirEntry& operator=(DirEntry&&) = default;
|
||||
|
||||
private:
|
||||
bool CanMode(dword u, dword g, dword o) const;
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
public:
|
||||
SFtp& Timeout(int ms) { ssh->timeout = ms; return *this; }
|
||||
SFtp& WaitStep(int ms) { ssh->waitstep = clamp(ms, 0, INT_MAX); return *this; }
|
||||
SFtp& ChunkSize(int sz) { ssh->chunk_size = clamp(sz, 128, INT_MAX); return *this; }
|
||||
SFtp& ChunkSize(int sz) { ssh->chunk_size = clamp(sz, 1, INT_MAX); return *this; }
|
||||
|
||||
// File
|
||||
SFtpHandle Open(const String& path, dword flags, long mode);
|
||||
|
|
@ -92,12 +92,12 @@ public:
|
|||
int64 GetPos(SFtpHandle handle);
|
||||
|
||||
// Read/Write
|
||||
int Get(SFtpHandle handle, void *ptr, int size = INT_MAX);
|
||||
bool Put(SFtpHandle handle, const void *ptr, int size);
|
||||
bool SaveFile(const char *path, const String& data);
|
||||
String LoadFile(const char *path);
|
||||
bool SaveFile(const char *path, Stream& in);
|
||||
void LoadFile(Stream& out, const char *path);
|
||||
int Get(SFtpHandle handle, void *ptr, int size = INT_MAX);
|
||||
bool Put(SFtpHandle handle, const void *ptr, int size);
|
||||
bool SaveFile(const char *path, const String& data);
|
||||
String LoadFile(const char *path);
|
||||
bool SaveFile(const char *path, Stream& in);
|
||||
void LoadFile(Stream& out, const char *path);
|
||||
|
||||
// Directory
|
||||
SFtpHandle OpenDir(const String& path);
|
||||
|
|
@ -115,7 +115,7 @@ public:
|
|||
bool GetAttrs(const String& path, SFtpAttrs& attrs);
|
||||
bool SetAttrs(SFtpHandle handle, const SFtpAttrs& attrs);
|
||||
bool SetAttrs(const String& path, const SFtpAttrs& attrs);
|
||||
// DirEntry GetInfo(const String& path) { return QueryAttr(path, SFTP_ATTR_INFO); }
|
||||
DirEntry GetInfo(const String& path);
|
||||
bool SetInfo(const DirEntry& entry) { return SetAttrs(entry.GetName(), ~entry); }
|
||||
int64 GetSize(const String& path) { return QueryAttr(path, SFTP_ATTR_SIZE); }
|
||||
bool SetSize(const String& path, int64 size) { return ModifyAttr(path, SFTP_ATTR_SIZE, size); }
|
||||
|
|
@ -163,7 +163,6 @@ private:
|
|||
SFTP_ATTR_PIPE,
|
||||
SFTP_ATTR_BLOCK,
|
||||
SFTP_ATTR_SPECIAL,
|
||||
SFTP_ATTR_INFO,
|
||||
SFTP_ATTR_UID,
|
||||
SFTP_ATTR_GID,
|
||||
SFTP_ATTR_PERMISSIONS,
|
||||
|
|
@ -175,51 +174,51 @@ private:
|
|||
|
||||
class SFtpStream : public BlockStream {
|
||||
protected:
|
||||
virtual void SetStreamSize(int64 size);
|
||||
virtual dword Read(int64 at, void *ptr, dword size);
|
||||
virtual void Write(int64 at, const void *data, dword size);
|
||||
virtual void SetStreamSize(int64 size);
|
||||
virtual dword Read(int64 at, void *ptr, dword size);
|
||||
virtual void Write(int64 at, const void *data, dword size);
|
||||
|
||||
public:
|
||||
virtual void Close();
|
||||
virtual bool IsOpen() const;
|
||||
virtual void Close();
|
||||
virtual bool IsOpen() const;
|
||||
|
||||
protected:
|
||||
SFtp *sftp;
|
||||
SFtpHandle handle;
|
||||
SFtp *sftp;
|
||||
SFtpHandle handle;
|
||||
|
||||
void SetPos(int64 pos);
|
||||
void Init(int64 size);
|
||||
void SetPos(int64 pos);
|
||||
void Init(int64 size);
|
||||
|
||||
public:
|
||||
operator bool() const { return IsOpen(); }
|
||||
operator bool() const { return IsOpen(); }
|
||||
|
||||
bool Open(SFtp& sftp, const char *filename, dword mode, int acm = 0644);
|
||||
SFtpStream(SFtp& sftp, const char *filename, dword mode, int acm = 0644);
|
||||
SFtpStream();
|
||||
~SFtpStream();
|
||||
SFtpHandle GetHandle() const { return handle; }
|
||||
bool Open(SFtp& sftp, const char *filename, dword mode, int acm = 0644);
|
||||
SFtpStream(SFtp& sftp, const char *filename, dword mode, int acm = 0644);
|
||||
SFtpStream();
|
||||
~SFtpStream();
|
||||
SFtpHandle GetHandle() const { return handle; }
|
||||
};
|
||||
|
||||
class SFtpFileOut : public SFtpStream {
|
||||
public:
|
||||
bool Open(SFtp& sftp, const char *fn, int acm = 0644) { return SFtpStream::Open(sftp, fn, CREATE|NOWRITESHARE, acm); }
|
||||
bool Open(SFtp& sftp, const char *fn, int acm = 0644) { return SFtpStream::Open(sftp, fn, CREATE|NOWRITESHARE, acm); }
|
||||
|
||||
SFtpFileOut(SFtp& sftp, const char *fn) { Open(sftp, fn); }
|
||||
SFtpFileOut() {}
|
||||
SFtpFileOut(SFtp& sftp, const char *fn) { Open(sftp, fn); }
|
||||
SFtpFileOut() {}
|
||||
};
|
||||
|
||||
class SFtpFileAppend : public SFtpStream {
|
||||
public:
|
||||
bool Open(SFtp& sftp, const char *fn) { return SFtpStream::Open(sftp, fn, APPEND|NOWRITESHARE); }
|
||||
bool Open(SFtp& sftp, const char *fn) { return SFtpStream::Open(sftp, fn, APPEND|NOWRITESHARE); }
|
||||
|
||||
SFtpFileAppend(SFtp& sftp, const char *fn) { Open(sftp, fn); }
|
||||
SFtpFileAppend() {}
|
||||
SFtpFileAppend(SFtp& sftp, const char *fn) { Open(sftp, fn); }
|
||||
SFtpFileAppend() {}
|
||||
};
|
||||
|
||||
class SFtpFileIn : public SFtpStream {
|
||||
public:
|
||||
bool Open(SFtp& sftp, const char *fn) { return SFtpStream::Open(sftp, fn, READ); }
|
||||
bool Open(SFtp& sftp, const char *fn) { return SFtpStream::Open(sftp, fn, READ); }
|
||||
|
||||
SFtpFileIn(SFtp& sftp, const char *fn) { Open(sftp, fn); }
|
||||
SFtpFileIn() {}
|
||||
SFtpFileIn(SFtp& sftp, const char *fn) { Open(sftp, fn); }
|
||||
SFtpFileIn() {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ public:
|
|||
|
||||
public:
|
||||
SshSession& Timeout(int ms) { ssh->timeout = ms; return *this; }
|
||||
SshSession& NonBlocking(bool b = true) { return Timeout(b ? 0 : Null);}
|
||||
SshSession& WaitStep(int ms) { ssh->waitstep = clamp(ms, 0, INT_MAX); return *this; }
|
||||
|
||||
SshSession& Keys(const String& prikey, const String& pubkey, const String& phrase = Null, bool fromfile = true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue