| 683 | } |
| 684 | |
| 685 | bool SFTPClient::listDirectory(const std::string& path, bool follow_symlinks, |
| 686 | std::vector<std::tuple<std::string /* filename */, std::string /* longentry */, LIBSSH2_SFTP_ATTRIBUTES /* attrs */>>& children_result) { |
| 687 | LIBSSH2_SFTP_HANDLE *dir_handle = libssh2_sftp_open_ex(sftp_session_, |
| 688 | path.c_str(), |
| 689 | path.length(), |
| 690 | 0 /* flags */, |
| 691 | 0 /* mode */, |
| 692 | LIBSSH2_SFTP_OPENDIR); |
| 693 | if (dir_handle == nullptr) { |
| 694 | last_error_.setLibssh2Error(libssh2_sftp_last_error(sftp_session_)); |
| 695 | logger_->log_error("Failed to open remote directory \"%s\", error: %s", path.c_str(), sftp_strerror(last_error_)); |
| 696 | return false; |
| 697 | } |
| 698 | const auto guard = gsl::finally([&dir_handle]() { |
| 699 | libssh2_sftp_close(dir_handle); |
| 700 | }); |
| 701 | |
| 702 | LIBSSH2_SFTP_ATTRIBUTES attrs; |
| 703 | std::vector<char> filename(4096U); |
| 704 | std::vector<char> longentry(4096U); |
| 705 | do { |
| 706 | int ret = libssh2_sftp_readdir_ex(dir_handle, |
| 707 | filename.data(), |
| 708 | filename.size(), |
| 709 | longentry.data(), |
| 710 | longentry.size(), |
| 711 | &attrs); |
| 712 | if (ret < 0) { |
| 713 | last_error_.setLibssh2Error(libssh2_sftp_last_error(sftp_session_)); |
| 714 | logger_->log_error("Failed to read remote directory \"%s\", error: %s", path.c_str(), sftp_strerror(last_error_)); |
| 715 | return false; |
| 716 | } else if (ret == 0) { |
| 717 | break; |
| 718 | } |
| 719 | if (follow_symlinks && attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS && LIBSSH2_SFTP_S_ISLNK(attrs.permissions)) { |
| 720 | std::stringstream new_path; |
| 721 | new_path << path << "/" << filename.data(); |
| 722 | auto orig_attrs = attrs; |
| 723 | if (!this->stat(new_path.str(), true /*follow_symlinks*/, attrs)) { |
| 724 | attrs = orig_attrs; |
| 725 | } |
| 726 | } |
| 727 | children_result.emplace_back(std::string(filename.data()), std::string(longentry.data()), std::move(attrs)); |
| 728 | } while (true); |
| 729 | return true; |
| 730 | } |
| 731 | |
| 732 | bool SFTPClient::stat(const std::string& path, bool follow_symlinks, LIBSSH2_SFTP_ATTRIBUTES& result) { |
| 733 | if (libssh2_sftp_stat_ex(sftp_session_, |