///////////////////////////////////////////////////////
| 1250 | |
| 1251 | //////////////////////////////////////////////////////////// |
| 1252 | Sftp::Result Sftp::upload(const std::filesystem::path& remotePath, |
| 1253 | const std::function<bool(void* data, std::size_t& size)>& callback, |
| 1254 | std::filesystem::perms permissions, |
| 1255 | bool truncate, |
| 1256 | bool append, |
| 1257 | std::uint64_t offset, |
| 1258 | const TimeoutWithPredicate& timeout) |
| 1259 | { |
| 1260 | if (!callback) |
| 1261 | return Result(Result::Value::Error); |
| 1262 | |
| 1263 | LIBSSH2_SFTP_HANDLE* handle{}; |
| 1264 | |
| 1265 | // Open the file for writing |
| 1266 | { |
| 1267 | const auto pathString = pathToUtf8(remotePath); |
| 1268 | const auto result = m_impl->waitForOperationComplete( |
| 1269 | [&] |
| 1270 | { |
| 1271 | if (handle = libssh2_sftp_open_ex(m_impl->sftpSession.get(), |
| 1272 | pathString.data(), |
| 1273 | static_cast<unsigned int>(pathString.size()), |
| 1274 | static_cast<unsigned int>(LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | |
| 1275 | (truncate ? LIBSSH2_FXF_TRUNC : 0) | |
| 1276 | (append ? LIBSSH2_FXF_APPEND : 0)), |
| 1277 | makePermissions(permissions), |
| 1278 | LIBSSH2_SFTP_OPENFILE); |
| 1279 | handle) |
| 1280 | return LIBSSH2_ERROR_NONE; |
| 1281 | |
| 1282 | return libssh2_session_last_errno(m_impl->ssh2Session.get()); |
| 1283 | }, |
| 1284 | timeout); |
| 1285 | |
| 1286 | if (!handle && (result == LIBSSH2_ERROR_EAGAIN)) |
| 1287 | return Result(Result::Value::Timeout); |
| 1288 | |
| 1289 | if (!handle) |
| 1290 | return makeError(m_impl->ssh2Session.get(), m_impl->sftpSession.get()); |
| 1291 | } |
| 1292 | |
| 1293 | // Seek to the offset if one was specified |
| 1294 | if (offset > 0) |
| 1295 | libssh2_sftp_seek64(handle, offset); |
| 1296 | |
| 1297 | // Write to the file |
| 1298 | { |
| 1299 | static constexpr auto bufferSizeStart = std::size_t{4 * 1024}; |
| 1300 | static constexpr auto bufferSizeMax = std::size_t{1024 * 1024}; |
| 1301 | auto bufferSize = bufferSizeStart; |
| 1302 | auto buffer = std::make_unique<char[]>(bufferSize); // NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) |
| 1303 | |
| 1304 | while (true) |
| 1305 | { |
| 1306 | std::size_t length = bufferSize; |
| 1307 | const auto stop = !callback(buffer.get(), length); |
| 1308 | const auto expand = (length == bufferSize); |
| 1309 | const auto* ptr = buffer.get(); |
nothing calls this directly
no test coverage detected