mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[datalogtool] Add datalogtool
This is a support tool for datalog file conversion (and eventually download/remote datalog file management).
This commit is contained in:
215
datalogtool/src/main/native/cpp/Sftp.cpp
Normal file
215
datalogtool/src/main/native/cpp/Sftp.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "Sftp.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace sftp;
|
||||
|
||||
Attributes::Attributes(sftp_attributes&& attr)
|
||||
: name{attr->name}, flags{attr->flags}, type{attr->type}, size{attr->size} {
|
||||
sftp_attributes_free(attr);
|
||||
}
|
||||
|
||||
static std::string GetError(sftp_session sftp) {
|
||||
switch (sftp_get_error(sftp)) {
|
||||
case SSH_FX_EOF:
|
||||
return "end of file";
|
||||
case SSH_FX_NO_SUCH_FILE:
|
||||
return "no such file";
|
||||
case SSH_FX_PERMISSION_DENIED:
|
||||
return "permission denied";
|
||||
case SSH_FX_FAILURE:
|
||||
return "SFTP failure";
|
||||
case SSH_FX_BAD_MESSAGE:
|
||||
return "SFTP bad message";
|
||||
case SSH_FX_NO_CONNECTION:
|
||||
return "SFTP no connection";
|
||||
case SSH_FX_CONNECTION_LOST:
|
||||
return "SFTP connection lost";
|
||||
case SSH_FX_OP_UNSUPPORTED:
|
||||
return "SFTP operation unsupported";
|
||||
case SSH_FX_INVALID_HANDLE:
|
||||
return "SFTP invalid handle";
|
||||
case SSH_FX_NO_SUCH_PATH:
|
||||
return "no such path";
|
||||
case SSH_FX_FILE_ALREADY_EXISTS:
|
||||
return "file already exists";
|
||||
case SSH_FX_WRITE_PROTECT:
|
||||
return "write protected filesystem";
|
||||
case SSH_FX_NO_MEDIA:
|
||||
return "no media inserted";
|
||||
default:
|
||||
return ssh_get_error(sftp->session);
|
||||
}
|
||||
}
|
||||
|
||||
Exception::Exception(sftp_session sftp)
|
||||
: runtime_error{GetError(sftp)}, err{sftp_get_error(sftp)} {}
|
||||
|
||||
File::~File() {
|
||||
if (m_handle) {
|
||||
sftp_close(m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
Attributes File::Stat() const {
|
||||
sftp_attributes attr = sftp_fstat(m_handle);
|
||||
if (!attr) {
|
||||
throw Exception{m_handle->sftp};
|
||||
}
|
||||
return Attributes{std::move(attr)};
|
||||
}
|
||||
|
||||
size_t File::Read(void* buf, uint32_t count) {
|
||||
auto rv = sftp_read(m_handle, buf, count);
|
||||
if (rv < 0) {
|
||||
throw Exception{m_handle->sftp};
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
File::AsyncId File::AsyncReadBegin(uint32_t len) const {
|
||||
int rv = sftp_async_read_begin(m_handle, len);
|
||||
if (rv < 0) {
|
||||
throw Exception{m_handle->sftp};
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
size_t File::AsyncRead(void* data, uint32_t len, AsyncId id) {
|
||||
auto rv = sftp_async_read(m_handle, data, len, id);
|
||||
if (rv == SSH_ERROR) {
|
||||
throw Exception{ssh_get_error(m_handle->sftp->session)};
|
||||
}
|
||||
if (rv == SSH_AGAIN) {
|
||||
return 0;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
size_t File::Write(wpi::span<const uint8_t> data) {
|
||||
auto rv = sftp_write(m_handle, data.data(), data.size());
|
||||
if (rv < 0) {
|
||||
throw Exception{m_handle->sftp};
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void File::Seek(uint64_t offset) {
|
||||
if (sftp_seek64(m_handle, offset) < 0) {
|
||||
throw Exception{m_handle->sftp};
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t File::Tell() const {
|
||||
return sftp_tell64(m_handle);
|
||||
}
|
||||
|
||||
void File::Rewind() {
|
||||
sftp_rewind(m_handle);
|
||||
}
|
||||
|
||||
void File::Sync() {
|
||||
if (sftp_fsync(m_handle) < 0) {
|
||||
throw Exception{m_handle->sftp};
|
||||
}
|
||||
}
|
||||
|
||||
Session::Session(std::string_view host, int port, std::string_view user,
|
||||
std::string_view pass)
|
||||
: m_host{host}, m_port{port}, m_username{user}, m_password{pass} {
|
||||
// Create a new SSH session.
|
||||
m_session = ssh_new();
|
||||
if (!m_session) {
|
||||
throw Exception{"The SSH session could not be allocated."};
|
||||
}
|
||||
|
||||
// Set the host, user, and port.
|
||||
ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.c_str());
|
||||
ssh_options_set(m_session, SSH_OPTIONS_USER, m_username.c_str());
|
||||
ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port);
|
||||
|
||||
// Set timeout to 3 seconds.
|
||||
int64_t timeout = 3L;
|
||||
ssh_options_set(m_session, SSH_OPTIONS_TIMEOUT, &timeout);
|
||||
|
||||
// Set other miscellaneous options.
|
||||
ssh_options_set(m_session, SSH_OPTIONS_STRICTHOSTKEYCHECK, "no");
|
||||
}
|
||||
|
||||
Session::~Session() {
|
||||
if (m_sftp) {
|
||||
sftp_free(m_sftp);
|
||||
}
|
||||
if (m_session) {
|
||||
ssh_free(m_session);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::Connect() {
|
||||
// Connect to the server.
|
||||
int rc = ssh_connect(m_session);
|
||||
if (rc != SSH_OK) {
|
||||
throw Exception{ssh_get_error(m_session)};
|
||||
}
|
||||
|
||||
// Authenticate with password.
|
||||
rc = ssh_userauth_password(m_session, nullptr, m_password.c_str());
|
||||
if (rc != SSH_AUTH_SUCCESS) {
|
||||
throw Exception{ssh_get_error(m_session)};
|
||||
}
|
||||
|
||||
// Allocate the SFTP session.
|
||||
m_sftp = sftp_new(m_session);
|
||||
if (!m_sftp) {
|
||||
throw Exception{ssh_get_error(m_session)};
|
||||
}
|
||||
|
||||
// Initialize.
|
||||
rc = sftp_init(m_sftp);
|
||||
if (rc != SSH_OK) {
|
||||
sftp_free(m_sftp);
|
||||
m_sftp = nullptr;
|
||||
throw Exception{ssh_get_error(m_session)};
|
||||
}
|
||||
}
|
||||
|
||||
void Session::Disconnect() {
|
||||
if (m_sftp) {
|
||||
sftp_free(m_sftp);
|
||||
m_sftp = nullptr;
|
||||
}
|
||||
ssh_disconnect(m_session);
|
||||
}
|
||||
|
||||
std::vector<Attributes> Session::ReadDir(const std::string& path) {
|
||||
sftp_dir dir = sftp_opendir(m_sftp, path.c_str());
|
||||
if (!dir) {
|
||||
throw Exception{m_sftp};
|
||||
}
|
||||
|
||||
std::vector<Attributes> rv;
|
||||
while (sftp_attributes attr = sftp_readdir(m_sftp, dir)) {
|
||||
rv.emplace_back(std::move(attr));
|
||||
}
|
||||
|
||||
sftp_closedir(dir);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void Session::Unlink(const std::string& filename) {
|
||||
if (sftp_unlink(m_sftp, filename.c_str()) < 0) {
|
||||
throw Exception{m_sftp};
|
||||
}
|
||||
}
|
||||
|
||||
File Session::Open(const std::string& filename, int accesstype, mode_t mode) {
|
||||
sftp_file f = sftp_open(m_sftp, filename.c_str(), accesstype, mode);
|
||||
if (!f) {
|
||||
throw Exception{m_sftp};
|
||||
}
|
||||
return File{std::move(f)};
|
||||
}
|
||||
Reference in New Issue
Block a user