ewmscp  ..
inputHandlerLibssh.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include "inputHandlerLibssh.h"
3 #include "block.h"
4 #include "copyRequestTypes.h"
5 #include "ewmscp.h"
6 
7 #include <fcntl.h>
8 #include <throwcall.h>
9 #include <errMsgQueue.h>
10 #include <unistd.h>
11 #include <string.h>
12 
13 #include <memory>
14 
15 namespace inputHandler {
16  decltype(libssh::factory) libssh::factory("sftp");
17 
18  static libsshCommon::sshOptions inputConfig("sshIn");
19 
22  }
23 
24  std::unique_ptr<base::reader> libssh::newReader(const std::string& aPath,
26  const genericStat& inititalStat) {
27  return std::unique_ptr<base::reader>(new readerLibssh(aPath,
28  *this,
29  state,
30  inititalStat));
31  }
32 
33 
34  bool libssh::readLinkTarget(const std::string& path,
35  std::vector<char>& target) {
36  auto targetString = sftp_readlink(sftp, path.c_str());
37  if (targetString == nullptr && sftp_get_error(sftp) == SSH_FX_NO_SUCH_FILE) {
38  return false;
39  }
40  throwcall::sftp::badval(targetString, nullptr, *this, "could not read link ", path);
41  auto linklength = strlen(targetString);
42  if (linklength >= target.size()) {
43  ssh_string_free_char(targetString);
44  throw std::runtime_error("link size increased after stat for " + path);
45  }
46  for (auto c = targetString; *c; c++) {
47  target.at(c - targetString) = *c;
48  }
49  ssh_string_free_char(targetString);
50  target[linklength] = '\0';
51 
52  return true;
53  }
54 
55 
56 
57  libssh::readerLibssh::readerLibssh(const std::string& aPath,
58  libsshCommon& aHandler,
60  const genericStat&inititalStat):
61  libsshIoCommon(aPath, aHandler),
62  reader(inititalStat) {
63  file = sftp_open(handler.sftp, path.c_str(), O_RDONLY, 0);
64  if (file == nullptr) {
65  if (sftp_get_error(handler.sftp) == SSH_FX_NO_SUCH_FILE) {
67  }
68  }
69  throwcall::sftp::badval(file, nullptr, handler, "can't open ", path, " for reading");
70  blockSize = readInitialStat.blksize;
71  }
72 
74  if (file != nullptr) {
75  if (isUnwinding()) {
76  if (sftp_close(file) == SSH_ERROR) {
78  path, "close during unwind ",
79  "sftp error ", sftp_get_error(handler.sftp),
80  ", ssh error ", ssh_get_error(handler.session));
81  }
82  return;
83  }
84  throwcall::sftp::badval(sftp_close(file), SSH_ERROR, handler,
85  "can't close ", path, " after reading");
86  }
87  }
88 
89 
90 
91 
92  void libssh::readerLibssh::seek(size_t pos) {
93  throwcall::sftp::good0(sftp_seek64(file, pos), handler,
94  "can't seek ", path, " to ", pos);
95  }
96 
98  b.clear(totalBytesRead);
99  bool lastblock = false;
100 
101  auto bytesToRead = b.max_size();
102 
103  while (b.size() + blockSize <= bytesToRead) {
105  auto bytes_read = sftp_read(file, b.bufferAt(b.size()), blockSize);
106  if (bytes_read < 0) {
107  throwcall::sftp::good0(1, handler, "read failed on ", path);
108  }
109  readRateLimit.update(bytes_read);
110  if (bytes_read == 0) {
111  lastblock = true;
112  if (totalBytesRead < readInitialStat.size) {
113  throw delayAdvisingError(path + " has shrunk while reading, (" +
114  std::to_string(readInitialStat.size) +
115  " -> " +
116  std::to_string(totalBytesRead) +
117  ")");
118  }
119  break;
120  }
121  totalBytesRead += bytes_read;
122  if (totalBytesRead > readInitialStat.size) {
123  throw delayAdvisingError(path + " has grown while reading, (" +
124  std::to_string(readInitialStat.size) +
125  " -> " +
126  std::to_string(totalBytesRead) +
127  ")");
128  }
129 
130  b.bump_size(bytes_read);
131  }
132 
133 
134  return lastblock;
135  }
136 
137 
139  auto stat = throwcall::sftp::badval(sftp_fstat(file), nullptr, handler,
140  "can't stat", path);
141  genericSftpStat readFinalStat(*stat, handler.getVfsStat(path));
142  sftp_attributes_free(stat);
143  if (readFinalStat.size != readInitialStat.size) {
144  throw delayAdvisingError("file size has changed (" +
145  std::to_string(readInitialStat.size) +
146  " -> " +
147  std::to_string(readFinalStat.size) +
148  ") during reading on " + path);
149  }
150 
151  if (!readFinalStat.isSameMtimeAs(readInitialStat)) {
152  throw delayAdvisingError("file " + path + " was modified (" +
153  std::to_string(std::chrono::duration_cast<std::chrono::duration<double>>(readFinalStat.getMtime() - readInitialStat.getMtime()).count()) +
154  "s different mtime) during reading");
155  }
156  }
157 
158 
160  const std::string& aPath):
161  Directory(aPath),
162  handler(aHandler) {
163  dir = throwcall::sftp::badval(sftp_opendir(handler.sftp, path.c_str()),
164  nullptr, handler,
165  "can't open directory ", path);
166  }
168  if (isUnwinding()) {
169  if (sftp_closedir(dir) == SSH_ERROR) {
171  path, "close during unwind ",
172  "sftp error ", sftp_get_error(handler.sftp),
173  ", ssh error ", ssh_get_error(handler.session));
174  }
175  } else {
176  throwcall::sftp::badval(sftp_closedir(dir), SSH_ERROR, handler,
177  "can't close directory");
178  }
179  }
180  std::unique_ptr<base::Directory::Entry> libssh::SftpDirectory::getNextEntry(bool /*ignoreMissing*/) {
181  while (auto entry = sftp_readdir(handler.sftp, dir)) {
182  if (entry->name[entry->name[0] != '.' ? 0 : entry->name[1] != '.' ? 1 : 2] == '\0') {
183  sftp_attributes_free(entry);
184  continue; // skip . .. and empty strings
185  }
186  auto genStat = std::unique_ptr<const genericStat>(new genericSftpStat(*entry,
187  handler.getVfsStat(path)));
188  auto retval = new Entry(entry->name, genStat);
189  sftp_attributes_free(entry);
190  return std::unique_ptr<Entry>(retval);
191  }
192  return nullptr;
193  }
194  std::unique_ptr<base::Directory> libssh::getDirectory(const std::string& path) {
195  return std::unique_ptr<Directory>(new SftpDirectory(*this, path));
196  }
197 
198 } //end namespace inputHandler
inputHandler::libssh::readerLibssh::checkUnchangedness
void checkUnchangedness() override
Definition: inputHandlerLibssh.cpp:138
block.h
inputHandlerLibssh.h
delayAdvisingError
class for exceptions that advise for delays Exceptions of this kind are to be thrown when circumstanc...
Definition: inputHandler.h:22
inputHandler::libssh::libssh
libssh()
Definition: inputHandlerLibssh.cpp:20
errMsgQueue.h
block::max_size
size_t max_size() const
Definition: block.h:22
inputHandler::libssh::newReader
std::unique_ptr< reader > newReader(const std::string &aPath, copyRequest::stateType &state, const genericStat &inititalStat) override
get a reader for the file at path
Definition: inputHandlerLibssh.cpp:24
inputHandler
Definition: inputHandler.h:29
inputHandler::libssh::SftpDirectory::~SftpDirectory
~SftpDirectory() noexcept(false) override
Definition: inputHandlerLibssh.cpp:167
errMsg::location
class for defining the location of a error message in the source code.
Definition: errMsgQueue.h:14
inputHandler::inputConfig
static daosFsCommon::daosOptions inputConfig("daosFsIn")
genericStat
generic stat abstraction class Used to abstract the variants of the stat structure.
Definition: genericStat.h:12
libsshCommon
Definition: libsshCommon.h:25
copyRequestTypes.h
inputHandler::libssh::SftpDirectory::handler
libsshCommon & handler
Definition: inputHandlerLibssh.h:41
libsshIoCommon::file
sftp_file file
Definition: libsshCommon.h:60
genericStat::getMtime
void getMtime(struct timespec &spec) const
Definition: genericStat.cpp:65
copyRequest::stateBitType::vanished
@ vanished
block::bump_size
void bump_size(size_t additionalBytes)
Definition: block.h:33
copyRequest::stateType
Definition: copyRequestTypes.h:66
libsshIoCommon
Definition: libsshCommon.h:56
libsshCommon::sshOptions
Definition: libsshCommon.h:30
genericStat::isSameMtimeAs
bool isSameMtimeAs(const genericStat &that) const
Definition: genericStat.cpp:87
readRateLimit
throttle::watch readRateLimit
errMsg::level::debug
@ debug
inputHandler::libssh::readLinkTarget
bool readLinkTarget(const std::string &path, std::vector< char > &target) override
read link target from a symlink
Definition: inputHandlerLibssh.cpp:34
ioHandle::blockSize
size_t blockSize
in bytes, block size to be used when reading or writing
Definition: ioHandle.h:17
genericStat::size
size_t size
Definition: genericStat.h:16
libsshIoCommon::path
const std::string path
Definition: libsshCommon.h:59
block::bufferAt
void * bufferAt(size_t offset)
only way to access the data in the block
Definition: block.cpp:28
throwcall.h
block
data block, used to hold the data that are being copied (or checksummed).
Definition: block.h:7
inputHandler::libssh::readerLibssh
Definition: inputHandlerLibssh.h:18
inputHandler::libssh::getDirectory
std::unique_ptr< Directory > getDirectory(const std::string &path) override
Definition: inputHandlerLibssh.cpp:194
libsshIoCommon::handler
libsshCommon & handler
Definition: libsshCommon.h:58
inputHandler::libssh::readerLibssh::seek
void seek(size_t pos) override
Definition: inputHandlerLibssh.cpp:92
inputHandler::libssh::readerLibssh::~readerLibssh
~readerLibssh() override
Definition: inputHandlerLibssh.cpp:73
throttle::watch::wait
void wait()
Definition: throttle.h:50
inputHandler::libssh::SftpDirectory
Definition: inputHandlerLibssh.h:40
errMsg::emit
void emit(level aLogLevel, const location &loc, const std::string &aObject, const std::string &aAction, const Args &... args)
function to create and enqueue a message, this is the only way that messages should be created!
Definition: errMsgQueue.h:148
inputHandler::libssh::SftpDirectory::dir
sftp_dir dir
Definition: inputHandlerLibssh.h:42
inputHandler::libssh::readerLibssh::readBlock
bool readBlock(block &b) override
Definition: inputHandlerLibssh.cpp:97
block::size
size_t size() const
Definition: block.h:16
inputHandler::libssh::factory
static factoryTemplate< libssh > factory
Definition: inputHandlerLibssh.h:15
libsshCommon::sftp
sftp_session sftp
Definition: libsshCommon.h:28
genericSftpStat
Definition: libsshCommon.h:16
inputHandler::libssh::SftpDirectory::getNextEntry
std::unique_ptr< Entry > getNextEntry(bool ignoreMissing) override
Definition: inputHandlerLibssh.cpp:180
block::clear
void clear(size_t aOffset)
Definition: block.h:28
inputHandler::libssh::SftpDirectory::SftpDirectory
SftpDirectory(libsshCommon &aHandler, const std::string &aPath)
Definition: inputHandlerLibssh.cpp:159
inputHandler::libssh::readerLibssh::readerLibssh
readerLibssh(const std::string &aPath, libsshCommon &aHandler, copyRequest::stateType &state, const genericStat &inititalStat)
Definition: inputHandlerLibssh.cpp:57
throwcall::sftp::badval
T badval(T call, t badvalue, libsshCommon &handler, const Args &... args)
Definition: libsshCommon.h:82
throttle::watch::update
void update(double units=1.0)
Definition: throttle.h:35
ewmscp.h
throwcall::sftp::good0
void good0(T call, libsshCommon &handler, const Args &... args)
Definition: libsshCommon.h:70