MCPcopy Create free account
hub / github.com/apache/nifi-minifi-cpp / getFile

Method getFile

extensions/sftp/client/SFTPClient.cpp:467–536  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

465}
466
467bool SFTPClient::getFile(const std::string& path, io::BaseStream& output, int64_t expected_size /*= -1*/) {
468 /**
469 * SFTP servers should not set the mode of an existing file on open
470 * (see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13, Page 33
471 * "The 'attrs' field is ignored if an existing file is opened."
472 * Unfortunately this is a later SFTP version specification than implemented by most servers.)
473 * But because this is the intuitively correct behaviour (especially when opening a file for read only),
474 * most servers (OpenSSH for example) implement it this way.
475 * mina-sshd, the server we use for testing, however did not until recently,
476 * causing all files we read to be set to 0000.
477 * The fix to make it behave correctly has been merged back to master, but not yet released:
478 * https://github.com/apache/mina-sshd/commit/19adb39e4706929b6e5a1b2df056a2b2a29fac4d
479 * If we encounter real servers that behave like this, a workaround would be to stat before opening the file
480 * and "re-setting" the mode we read earlier on open.
481 * An another option would be to patch libssh2 to not send permissions in attrs when opening a file for read only.
482 */
483 LIBSSH2_SFTP_HANDLE *file_handle = libssh2_sftp_open(sftp_session_, path.c_str(), LIBSSH2_FXF_READ, 0 /*mode*/);
484 if (file_handle == nullptr) {
485 int ssh_errno = libssh2_session_last_errno(ssh_session_);
486 /* We can only get the sftp error in this case if the ssh error is a protocol error */
487 if (ssh_errno == LIBSSH2_ERROR_SFTP_PROTOCOL) {
488 last_error_.setLibssh2Error(libssh2_sftp_last_error(sftp_session_));
489 logger_->log_error("Failed to open remote file \"%s\", error: %s", path.c_str(), sftp_strerror(last_error_));
490 } else {
491 last_error_.setSftpError(SFTPError::IoError);
492 char *err_msg = nullptr;
493 libssh2_session_last_error(ssh_session_, &err_msg, nullptr, 0);
494 logger_->log_error("Failed to open remote file \"%s\" due to an underlying SSH error: %s", path.c_str(), err_msg);
495 }
496 return false;
497 }
498 const auto guard = gsl::finally([&file_handle]() {
499 libssh2_sftp_close(file_handle);
500 });
501
502 const size_t buf_size = expected_size < 0 ? MAX_BUFFER_SIZE : std::min<size_t>(expected_size, MAX_BUFFER_SIZE);
503 std::vector<uint8_t> buf(buf_size);
504 uint64_t total_read = 0U;
505 do {
506 ssize_t read_ret = libssh2_sftp_read(file_handle, reinterpret_cast<char*>(buf.data()), buf.size());
507 if (read_ret < 0) {
508 last_error_.setSftpError(SFTPError::IoError);
509 logger_->log_error("Failed to read remote file \"%s\"", path.c_str());
510 return false;
511 } else if (read_ret == 0) {
512 logger_->log_trace("EOF while reading remote file \"%s\"", path.c_str());
513 break;
514 }
515 logger_->log_trace("Read %d bytes from remote file \"%s\"", read_ret, path.c_str());
516 total_read += read_ret;
517 int remaining = read_ret;
518 while (remaining > 0) {
519 int write_ret = output.write(buf.data() + (read_ret - remaining), remaining);
520 if (write_ret < 0) {
521 last_error_.setLibssh2Error(LIBSSH2_FX_OK);
522 logger_->log_error("Failed to write output");
523 return false;
524 }

Callers 5

notifyStopMethod · 0.80
create_new_captureMethod · 0.80
onScheduleMethod · 0.80
onTriggerMethod · 0.80
processMethod · 0.80

Calls 6

sftp_strerrorFunction · 0.85
c_strMethod · 0.80
log_errorMethod · 0.80
log_traceMethod · 0.80
sizeMethod · 0.45
writeMethod · 0.45

Tested by

no test coverage detected