GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/cxx_sshclients.cpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 68 183 37.2%
Functions: 15 38 39.5%
Branches: 30 168 17.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28 #include "gate/net/sshclients.hpp"
29 #include "gate/exceptions.hpp"
30
31 namespace gate
32 {
33 namespace net
34 {
35
36 2 SshClient::~SshClient() noexcept
37 {
38 1 gate_sshclient_disconnect(&this->impl);
39 1 gate_sshclient_release(&this->impl);
40 1 }
41 1 gate_sshclient_t* SshClient::c_impl()
42 {
43 1 return &this->impl;
44 }
45 1 SshClient::SshClient(String const& server, uint16_t port, String const& user, String const& password)
46 {
47 1 result_t result = gate_sshclient_create(&this->impl, server.c_impl(), port);
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
49 1 result = gate_sshclient_connect(&this->impl, user.c_impl(), password.c_impl(), 0);
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
51 {
52 gate_sshclient_release(&this->impl);
53 GATEXX_RAISE_EXCEPTION(result, NULL, 0);
54 }
55 1 }
56
57 SshClient::SshClient(String const& server, uint16_t port, String const& user,
58 String const& publicKey, String const& privateKey, String const& passPhrase)
59 {
60 result_t result = gate_sshclient_create(&this->impl, server.c_impl(), port);
61 GATEXX_CHECK_EXCEPTION(result);
62 result = gate_sshclient_connect_keys(&this->impl, user.c_impl(),
63 publicKey.c_impl(), privateKey.c_impl(), passPhrase.c_impl(), 0);
64 if (GATE_FAILED(result))
65 {
66 gate_sshclient_release(&this->impl);
67 GATEXX_RAISE_EXCEPTION(result, NULL, 0);
68 }
69 }
70
71
72 1 Ref<SshClient> SshClient::create(String const& server, uint16_t port, String const& user, String const& password)
73 {
74
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 Ptr<SshClient> ptr(new SshClient(server, port, user, password));
75
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 Ref<SshClient> ref(gate::moveRef(ptr));
76 2 return ref;
77 }
78
79 Ref<SshClient> SshClient::create(String const& server, uint16_t port, String const& user,
80 String const& publicKey, String const& privateKey, String const& passPhrase)
81 {
82 Ptr<SshClient> ptr(new SshClient(server, port, user, publicKey, privateKey, passPhrase));
83 Ref<SshClient> ref(gate::moveRef(ptr));
84 return ref;
85 }
86
87
88 1 SshFtp::SshFtp(SshClientRef connectedClient)
89 1 : client(connectedClient)
90 {
91
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!client)
92 {
93 GATEXX_RAISE_ERROR(results::NullPointer);
94 }
95
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_sshclient_open_sftp(client->c_impl(), &this->impl);
96
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
97 1 }
98 1 SshFtp::~SshFtp() noexcept
99 {
100 1 gate_sshclient_close_sftp(&this->impl);
101 1 }
102
103 void SshFtp::createDirectory(String const& path)
104 {
105 result_t result = gate_sshclient_sftp_mkdir(&this->impl, path.c_impl());
106 GATEXX_CHECK_EXCEPTION(result);
107 }
108 void SshFtp::removeDirectory(String const& path)
109 {
110 result_t result = gate_sshclient_sftp_rmdir(&this->impl, path.c_impl());
111 GATEXX_CHECK_EXCEPTION(result);
112 }
113 void SshFtp::deleteFile(String const& path)
114 {
115 result_t result = gate_sshclient_sftp_unlink(&this->impl, path.c_impl());
116 GATEXX_CHECK_EXCEPTION(result);
117 }
118 void SshFtp::move(String const& path, String const& newPath)
119 {
120 result_t result = gate_sshclient_sftp_rename(&this->impl, path.c_impl(), newPath.c_impl());
121 GATEXX_CHECK_EXCEPTION(result);
122 }
123
124 1 File::Properties SshFtp::getProperties(String const& path)
125 {
126 gate_file_properties_t props;
127
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t result = gate_sshclient_sftp_stat(&this->impl, path.c_impl(), &props);
128
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
129
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return File::Properties(props);
130 }
131
132 struct GATE_API_LOCAL SshFtp_listEntries_data
133 {
134 File::callback_t const* callback;
135 void* userparam;
136 };
137
138 static gate_bool_t SshFtp_listEntries_cb(gate_file_entry_t const* entry, void* userparam)
139 {
140 SshFtp_listEntries_data* data = static_cast<SshFtp_listEntries_data*>(userparam);
141 File::Entry fileEntry((*entry));
142 bool_t continueListing = true;
143 File::callback_t cb = *(data->callback);
144 try
145 {
146 cb(&fileEntry, data->userparam, &continueListing);
147 }
148 catch (...) {}
149 return continueListing;
150 }
151
152 void SshFtp::listEntries(String const& dirpath, File::callback_t const& callback, void* userparam)
153 {
154 SshFtp_listEntries_data data;
155 data.callback = &callback;
156 data.userparam = userparam;
157
158 result_t result = gate_sshclient_sftp_listdir(&this->impl, dirpath.c_impl(), &SshFtp_listEntries_cb, &data);
159 GATEXX_CHECK_EXCEPTION(result);
160 }
161
162 1 File::pathmap_t SshFtp::listEntryPaths(String const& dirpath)
163 {
164 1 File::pathmap_t ret;
165 gate_sshclient_sftp_handle_t sftpHandle;
166 1 bool_t continueRead = true;
167
168
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t result = gate_sshclient_sftp_opendir(&this->impl, dirpath.c_impl(), &sftpHandle);
169
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
170
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 while (continueRead)
171 {
172
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 File::Entry fileEntry;
173
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 result = gate_sshclient_sftp_readdir(&sftpHandle, &fileEntry);
174
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 GATE_BREAK_IF_FAILED(result);
175
3/6
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
18 ret.add(fileEntry.getPath(), fileEntry.getName());
176 }
177
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 gate_sshclient_sftp_close(&sftpHandle);
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result != GATE_RESULT_NODATA)
180 {
181 GATEXX_CHECK_EXCEPTION(result);
182 }
183 2 return ret;
184 }
185
186 1 gate_sshclient_sftp_t* SshFtp::c_impl()
187 {
188 1 return &this->impl;
189 }
190
191 1 SshClientRef SshFtp::getClient() const
192 {
193 1 return this->client;
194 }
195
196
197
198 1 SshFtpFile::SshFtpFile(SshFtp& sftp, String const& path, enumint_t streamOpenFlags)
199 1 : client(sftp.getClient())
200 {
201
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_sshclient_sftp_open(sftp.c_impl(), path.c_impl(), streamOpenFlags, &this->impl);
202
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
203 1 }
204 1 SshFtpFile::~SshFtpFile() noexcept
205 {
206 1 gate_sshclient_sftp_close(&this->impl);
207 1 }
208
209 1 size_t SshFtpFile::read(char* buffer, gate_size_t capacity)
210 {
211 1 gate_size_t received = 0;
212
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_sshclient_sftp_read(&this->impl, buffer, capacity, &received);
213
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
214 1 return received;
215 }
216 size_t SshFtpFile::write(char const* buffer, gate_size_t length)
217 {
218 gate_size_t written = 0;
219 result_t result = gate_sshclient_sftp_write(&this->impl, buffer, length, &written);
220 GATEXX_CHECK_EXCEPTION(result);
221 return written;
222 }
223 1 void SshFtpFile::seek(gate_uint64_t position)
224 {
225 1 result_t result = gate_sshclient_sftp_seek(&this->impl, position);
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
227 1 }
228 1 uint64_t SshFtpFile::tell()
229 {
230 1 gate_uint64_t pos = 0;
231
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_sshclient_sftp_tell(&this->impl, &pos);
232
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
233 1 return pos;
234 }
235
236 gate_sshclient_sftp_handle_t* SshFtpFile::c_impl()
237 {
238 return &this->impl;
239 }
240 SshClientRef SshFtpFile::getClient() const
241 {
242 return this->client;
243 }
244
245
246 enumint_t const SshCommandChannel::StreamType_Default = GATE_SSHCLIENT_STREAMTYPE_DEFAULT;
247 enumint_t const SshCommandChannel::StreamType_Error = GATE_SSHCLIENT_STREAMTYPE_ERROR;
248
249 SshCommandChannel::SshCommandChannel(SshClientRef const& connectedClient)
250 : client(connectedClient),
251 impl(NULL)
252 {
253 result_t result = gate_sshclient_channel_open(this->client->c_impl(), &this->impl);
254 GATEXX_CHECK_EXCEPTION(result);
255 }
256 SshCommandChannel::~SshCommandChannel() noexcept
257 {
258 gate_sshclient_channel_free(&this->impl);
259 }
260
261 void SshCommandChannel::execute(String const& command)
262 {
263 result_t result = gate_sshclient_channel_exec(&this->impl, command.c_impl());
264 GATEXX_CHECK_EXCEPTION(result);
265 }
266 bool_t SshCommandChannel::canRead(enumint_t streamType)
267 {
268 gate_bool_t value = false;
269 result_t result = gate_sshclient_channel_canread(&this->impl, streamType, &value);
270 GATEXX_CHECK_EXCEPTION(result);
271 return value;
272 }
273 size_t SshCommandChannel::read(char* buffer, gate_size_t capacity, enumint_t streamType)
274 {
275 gate_size_t retrieved = 0;
276 result_t result = gate_sshclient_channel_read(&this->impl, streamType, buffer, capacity, &retrieved);
277 GATEXX_CHECK_EXCEPTION(result);
278 return retrieved;
279 }
280 size_t SshCommandChannel::write(char const* buffer, gate_size_t length, enumint_t streamType)
281 {
282 gate_size_t processed = 0;
283 result_t result = gate_sshclient_channel_write(&this->impl, streamType, buffer, length, &processed);
284 GATEXX_CHECK_EXCEPTION(result);
285 return processed;
286 }
287 bool SshCommandChannel::eof()
288 {
289 return gate_sshclient_channel_eof(&this->impl);
290 }
291 void SshCommandChannel::sendEof()
292 {
293 result_t result = gate_sshclient_channel_send_eof(&this->impl);
294 GATEXX_CHECK_EXCEPTION(result);
295 }
296 void SshCommandChannel::waitEof()
297 {
298 result_t result = gate_sshclient_channel_wait_eof(&this->impl);
299 GATEXX_CHECK_EXCEPTION(result);
300 }
301 void SshCommandChannel::setEnv(String const& name, String const& value)
302 {
303 result_t result = gate_sshclient_channel_setenv(&this->impl, name.c_impl(), value.c_impl());
304 GATEXX_CHECK_EXCEPTION(result);
305 }
306 void SshCommandChannel::getExitSignal(String* signal, String* errmsg, String* langtag)
307 {
308 gate_string_t strsig = GATE_STRING_INIT_EMPTY;
309 gate_string_t strerr = GATE_STRING_INIT_EMPTY;
310 gate_string_t strlang = GATE_STRING_INIT_EMPTY;
311 result_t result = gate_sshclient_channel_get_exit_signal(&this->impl, &strsig, &strerr, &strlang);
312 GATEXX_CHECK_EXCEPTION(result);
313 try
314 {
315 if (signal) *signal = String::createFrom(strsig);
316 if (errmsg) *errmsg = String::createFrom(strerr);
317 if (langtag) *langtag = String::createFrom(strlang);
318 }
319 catch (...)
320 {
321 gate_string_release(&strlang);
322 gate_string_release(&strerr);
323 gate_string_release(&strsig);
324 throw;
325 }
326 gate_string_release(&strlang);
327 gate_string_release(&strerr);
328 gate_string_release(&strsig);
329 }
330 int SshCommandChannel::getExitStatus()
331 {
332 int status = 0;
333 result_t result = gate_sshclient_channel_get_exit_status(&this->impl, &status);
334 GATEXX_CHECK_EXCEPTION(result);
335 return status;
336 }
337
338 } // end of namespace net
339 } // end of namespace gate
340