1 #include "SSH.h"
2
3 namespace Upp {
4
5 #define LLOG(x) do { if(SSH::sTrace) RLOG(SSH::GetName(ssh->otype, ssh->oid) << x); } while(false)
6 #define LDUMPHEX(x) do { if(SSH::sTraceVerbose) RDUMPHEX(x); } while(false)
7
OpenRead(const String & path,ScpAttrs & attrs)8 bool Scp::OpenRead(const String& path, ScpAttrs& attrs)
9 {
10 Zero(attrs);
11 return Run([=, &attrs]() mutable {
12 LIBSSH2_CHANNEL *ch = libssh2_scp_recv2(ssh->session, path, &attrs);
13 if(!ch && !WouldBlock()) {
14 LLOG("Unable to open file " << path);
15 SetError(-1);
16 }
17 if(ch) {
18 channel = MakeOne<LIBSSH2_CHANNEL*>(ch);
19 LLOG("File " << path << " opened.");
20 }
21 return ch;
22 });
23 }
24
OpenWrite(const String & path,int64 size,long mode)25 bool Scp::OpenWrite(const String& path, int64 size, long mode)
26 {
27 return Run([=]() mutable {
28 LIBSSH2_CHANNEL *ch = libssh2_scp_send64(ssh->session, path, mode, size, 0, 0);
29 if(!ch && !WouldBlock()) {
30 LLOG("Unable to open file " << path);
31 SetError(-1);
32 }
33 if(ch) {
34 channel = MakeOne<LIBSSH2_CHANNEL*>(ch);
35 LLOG("File " << path << " opened.");
36 }
37 return ch;
38 });
39 }
40
Load(Stream & s,ScpAttrs a,int64 maxsize)41 bool Scp::Load(Stream& s, ScpAttrs a, int64 maxsize)
42 {
43 bool nowait = false;
44 int64 done_ = 0;
45 int64 size = a.st_size;
46 String msg;
47
48 if(size < 0 || size >= maxsize) {
49 msg = "Invald stream size.";
50 }
51 else
52 while(done_ < size && !IsEof() && !IsError()) {
53 int csz = (int) min<int64>(size - done_, ssh->chunk_size);
54 Buffer<char> chunk(csz, 0);
55 int n = Get(chunk, csz);
56 if(n > 0) {
57 done_ += n;
58 s.Put(chunk, n);
59 if((nowait = WhenProgress(done_, size))) {
60 msg = "File transfer aborted.";
61 break;
62 }
63 }
64 }
65 return Shut(msg, nowait);
66 }
67
Save(Stream & s)68 bool Scp::Save(Stream& s)
69 {
70 bool nowait = false;
71 int64 done_ = 0;
72 int64 size = s.GetSize();
73 String msg;
74
75 Buffer<char> chunk(ssh->chunk_size, 0);
76
77 while(done_ < size && !IsEof() && !IsError()) {
78 int l = s.Get(chunk, (int) min<int64>(size - done_, ssh->chunk_size));
79 int n = Put(chunk, l);
80 if(n > 0) {
81 done_ += n;
82 if(n < l)
83 s.Seek(n);
84 if((nowait = WhenProgress(done_, size))) {
85 msg = "File transfer aborted.";;
86 break;
87 }
88 }
89 }
90 return Shut(msg, nowait);
91 }
92
SaveFile(const char * path,const String & data)93 bool Scp::SaveFile(const char *path, const String& data)
94 {
95 StringStream s(data);
96 return OpenWrite(path, s.GetSize()) && Save(s);
97 }
98
LoadFile(const char * path)99 String Scp::LoadFile(const char *path)
100 {
101 StringStream s;
102 ScpAttrs attrs;
103 if(OpenRead(path, attrs))
104 Load(s, attrs, INT_MAX);
105 return pick(s.GetResult());
106 }
107
SaveFile(const char * path,Stream & in)108 bool Scp::SaveFile(const char *path, Stream& in)
109 {
110 return OpenWrite(path, in.GetSize()) && Save(in);
111 }
112
LoadFile(Stream & out,const char * path)113 bool Scp::LoadFile(Stream& out, const char *path)
114 {
115 ScpAttrs attrs;
116 return OpenRead(path, attrs) && Load(out, attrs);
117 }
118 }