GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/cxx_sshclients.cpp
Date: 2025-09-22 22:57:09
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