diff --git a/src/mavsdk/core/filesystem_include.h b/src/mavsdk/core/filesystem_include.h deleted file mode 100644 index 1d989c5732..0000000000 --- a/src/mavsdk/core/filesystem_include.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#if __has_include() -#include -namespace fs = std::filesystem; -#elif __has_include() -#include -namespace fs = std::experimental::filesystem; -#else -#error "Missing the header." -#endif diff --git a/src/mavsdk/core/fs.cpp b/src/mavsdk/core/fs.cpp index 4f8ecc98e2..d50cb8ae16 100644 --- a/src/mavsdk/core/fs.cpp +++ b/src/mavsdk/core/fs.cpp @@ -1,21 +1,4 @@ -#if defined(WINDOWS) -#include "tronkko_dirent.h" -#include "stackoverflow_unistd.h" -#include -#define mkdir(D, M) _mkdir(D) -#else -#include -#include -#endif - -#include -#include -#include -#include -#include - #include "fs.h" -#include "filesystem_include.h" #include "log.h" #include "unused.h" @@ -27,88 +10,76 @@ namespace mavsdk { -bool fs_exists(const fs::path& path) -{ - return fs::exists(path); -} - -uint32_t fs_file_size(const std::string& filename) -{ - struct stat stat_buf; - int rc = stat(filename.c_str(), &stat_buf); - return (rc == 0) ? stat_buf.st_size : 0; -} - -static void relative_dir_base_split(const std::string& path, std::string& dir, std::string& base) -{ - std::string::size_type slash_pos = path.rfind(path_separator); - if (slash_pos != std::string::npos) { - slash_pos++; - dir = path.substr(0, slash_pos); - base = path.substr(slash_pos); - } else { - dir.clear(); - base = path; - } -} - -std::string fs_filename(const std::string& path) -{ - std::string dir; - std::string base; - relative_dir_base_split(path, dir, base); - return base; -} - -std::string fs_canonical(const std::string& path) -{ - std::deque st; - std::string res; - - int len = path.length(); - - int index = 0; - while (index < len) { - int next_index = path.find(path_separator, index); - if (next_index == -1) { - next_index = path.size(); - } - - std::string dir = path.substr(index, next_index - index); - - if (dir.compare("..") == 0 && !st.empty()) { - st.pop_back(); - } else if (dir.length() != 0 && dir.compare(".") != 0) { - st.push_back(dir); - } - - index = next_index + path_separator.size(); - } - - if (path.rfind(path_separator, path_separator.size() - 1) != 0) { - char buffer[PATH_MAX]; - if (getcwd(buffer, sizeof(buffer)) != nullptr) { - res.append(buffer); - if (!st.empty()) { - res.append(path_separator); - } - } - } else { - res.append(path_separator); - } - - while (!st.empty()) { - std::string temp = st.front(); - if (st.size() != 1) { - res.append(temp + path_separator); - } else { - res.append(temp); - } - st.pop_front(); - } - - return res; -} +//static void relative_dir_base_split(const std::string& path, std::string& dir, std::string& base) +//{ +// std::string::size_type slash_pos = path.rfind(path_separator); +// if (slash_pos != std::string::npos) { +// slash_pos++; +// dir = path.substr(0, slash_pos); +// base = path.substr(slash_pos); +// } else { +// dir.clear(); +// base = path; +// } +//} + +//std::string fs_filename(const std::string& path) +//{ +// std::string dir; +// std::string base; +// relative_dir_base_split(path, dir, base); +// return base; +//} + +//std::string fs_canonical(const std::string& path) +//{ +// std::deque st; +// std::string res; +// +// int len = path.length(); +// +// int index = 0; +// while (index < len) { +// int next_index = path.find(path_separator, index); +// if (next_index == -1) { +// next_index = path.size(); +// } +// +// std::string dir = path.substr(index, next_index - index); +// +// if (dir.compare("..") == 0 && !st.empty()) { +// st.pop_back(); +// } else if (dir.length() != 0 && dir.compare(".") != 0) { +// st.push_back(dir); +// } +// +// index = next_index + path_separator.size(); +// } +// +// if (path.rfind(path_separator, path_separator.size() - 1) != 0) { +// char buffer[PATH_MAX]; +// if (getcwd(buffer, sizeof(buffer)) != nullptr) { +// res.append(buffer); +// if (!st.empty()) { +// res.append(path_separator); +// } +// } +// } else { +// res.append(path_separator); +// } +// +// while (!st.empty()) { +// std::string temp = st.front(); +// if (st.size() != 1) { +// res.append(temp + path_separator); +// } else { +// res.append(temp); +// } +// st.pop_front(); +// } +// +// return res; +//} bool fs_create_directory(const std::string& path) { diff --git a/src/mavsdk/core/fs.h b/src/mavsdk/core/fs.h index 5559f89d6c..df7594d7c2 100644 --- a/src/mavsdk/core/fs.h +++ b/src/mavsdk/core/fs.h @@ -9,16 +9,8 @@ namespace fs = std::filesystem; namespace mavsdk { -#if defined(WINDOWS) -const std::string path_separator = "\\"; -#else -const std::string path_separator = "/"; -#endif - bool fs_exists(const fs::path& filename); -uint32_t fs_file_size(const std::string& filename); - std::string fs_filename(const std::string& path); std::string fs_canonical(const std::string& path); diff --git a/src/mavsdk/core/mavlink_ftp_server.cpp b/src/mavsdk/core/mavlink_ftp_server.cpp index 1819f2033c..cef2c24f98 100644 --- a/src/mavsdk/core/mavlink_ftp_server.cpp +++ b/src/mavsdk/core/mavlink_ftp_server.cpp @@ -1,22 +1,13 @@ -#include "mavlink_ftp_server.h" -#include "server_component_impl.h" +#include #include #include +#include -#if defined(WINDOWS) -#include "tronkko_dirent.h" -#include "stackoverflow_unistd.h" -#else -#include -#endif -#include -#include - +#include "mavlink_ftp_server.h" +#include "server_component_impl.h" #include "unused.h" #include "crc32.h" #include "fs.h" -#include -#include namespace mavsdk { @@ -415,7 +406,7 @@ void MavlinkFtpServer::_work_list(const PayloadHeader& payload, PayloadHeader& r void MavlinkFtpServer::_work_open_file_readonly( const PayloadHeader& payload, PayloadHeader& response) { - if (_session_info.fd >= 0) { + if (_session_info.ifstream.is_open()) { _reset(); } @@ -452,22 +443,28 @@ void MavlinkFtpServer::_work_open_file_readonly( } if (!fs_exists(path)) { - LogWarn() << "FTP: Open failed - file not found"; + LogErr() << "FTP: Open failed - file doesn't exist"; response.opcode = Opcode::RSP_NAK; response.size = 1; response.data[0] = ServerResult::ERR_FAIL_FILE_DOES_NOT_EXIST; return; } - uint32_t file_size = fs_file_size(path); + std::error_code ec; + auto file_size = static_cast(fs::file_size(path, ec)); + if (ec) { + LogErr() << "Could not determine file size of '" << path << "': " << ec.message(); + return; + } if (_debugging) { LogDebug() << "Determined filesize to be: " << file_size << " bytes"; } - int fd = ::open(path.c_str(), O_RDONLY); + std::ifstream ifstream; + ifstream.open(path, std::ios::in | std::ios::binary); - if (fd < 0) { + if (!ifstream.is_open()) { LogWarn() << "FTP: Open failed"; response.opcode = Opcode::RSP_NAK; response.size = 1; @@ -475,20 +472,20 @@ void MavlinkFtpServer::_work_open_file_readonly( return; } - _session_info.fd = fd; + _session_info.ifstream = std::move(ifstream); _session_info.file_size = file_size; _session_info.stream_download = false; response.opcode = Opcode::RSP_ACK; response.session = 0; response.size = sizeof(uint32_t); - memcpy(response.data, &file_size, response.size); + std::memcpy(response.data, &file_size, response.size); } void MavlinkFtpServer::_work_open_file_writeonly( const PayloadHeader& payload, PayloadHeader& response) { - if (_session_info.fd >= 0) { + if (_session_info.ofstream.is_open()) { _reset(); } @@ -533,20 +530,29 @@ void MavlinkFtpServer::_work_open_file_writeonly( return; } - uint32_t file_size = fs_file_size(path); + std::error_code ec; + auto file_size = static_cast(fs::file_size(path, ec)); + if (ec) { + LogErr() << "Could not determine file size of '" << path << "': " << ec.message(); + return; + } - int fd = ::open(path.c_str(), O_WRONLY, 0666); + if (_debugging) { + LogDebug() << "Determined filesize to be: " << file_size << " bytes"; + } + + std::ofstream ofstream; + ofstream.open(path, std::ios::out | std::ios::binary); - if (fd < 0) { + if (!ofstream.is_open()) { LogWarn() << "FTP: Open failed"; response.opcode = Opcode::RSP_NAK; response.size = 1; - response.data[0] = - (errno == ENOENT) ? ServerResult::ERR_FAIL_FILE_DOES_NOT_EXIST : ServerResult::ERR_FAIL; + response.data[0] = ServerResult::ERR_FAIL; return; } - _session_info.fd = fd; + _session_info.ofstream = std::move(ofstream); _session_info.file_size = file_size; _session_info.stream_download = false; @@ -558,7 +564,7 @@ void MavlinkFtpServer::_work_open_file_writeonly( void MavlinkFtpServer::_work_create_file(const PayloadHeader& payload, PayloadHeader& response) { - if (_session_info.fd >= 0) { + if (_session_info.ofstream.is_open()) { _reset(); } @@ -594,9 +600,10 @@ void MavlinkFtpServer::_work_create_file(const PayloadHeader& payload, PayloadHe LogDebug() << "Creating file: " << path; } - int fd = ::open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666); + std::ofstream ofstream; + ofstream.open(path, std::ios::out | std::ios::binary); - if (fd < 0) { + if (!ofstream.is_open()) { LogWarn() << "FTP: Open failed"; response.opcode = Opcode::RSP_NAK; response.size = 1; @@ -604,7 +611,8 @@ void MavlinkFtpServer::_work_create_file(const PayloadHeader& payload, PayloadHe return; } - _session_info.fd = fd; + _session_info.ofstream = std::move(ofstream); + _session_info.stream_download = false; _session_info.file_size = 0; response.session = 0; @@ -614,7 +622,7 @@ void MavlinkFtpServer::_work_create_file(const PayloadHeader& payload, PayloadHe void MavlinkFtpServer::_work_read(const PayloadHeader& payload, PayloadHeader& response) { - if (payload.session != 0 || _session_info.fd < 0) { + if (payload.session != 0 || !_session_info.ifstream.is_open()) { _reset(); } @@ -623,26 +631,33 @@ void MavlinkFtpServer::_work_read(const PayloadHeader& payload, PayloadHeader& r response.opcode = Opcode::RSP_NAK; response.size = 1; response.data[0] = ServerResult::ERR_EOF; + if (_debugging) { + LogDebug() << "Reached EOF reading"; + } return; } - if (lseek(_session_info.fd, payload.offset, SEEK_SET) < 0) { + _session_info.ifstream.seekg(payload.offset); + if (_session_info.ifstream.fail()) { response.opcode = Opcode::RSP_NAK; response.size = 1; response.data[0] = ServerResult::ERR_FAIL; + LogWarn() << "Seek failed"; return; } - auto bytes_read = ::read(_session_info.fd, &response.data[0], max_data_length); + _session_info.ifstream.read(reinterpret_cast(response.data), payload.size); - if (bytes_read < 0) { - // Negative return indicates error other than EOF. + if (_session_info.ifstream.fail()) { response.opcode = Opcode::RSP_NAK; response.size = 1; response.data[0] = ServerResult::ERR_FAIL; + LogWarn() << "Read failed"; return; } + const uint32_t bytes_read = _session_info.ifstream.gcount(); + response.size = bytes_read; response.opcode = Opcode::RSP_ACK; } @@ -650,47 +665,48 @@ void MavlinkFtpServer::_work_read(const PayloadHeader& payload, PayloadHeader& r void MavlinkFtpServer::_work_burst(const PayloadHeader& payload, PayloadHeader& response) { // TODO: implement burst + UNUSED(payload); UNUSED(response); - if (payload.session != 0 && _session_info.fd < 0) { - _reset(); - } + // if (payload.session != 0 && _session_info.fd < 0) { + // _reset(); + //} - // Setup for streaming sends - _session_info.stream_download = true; - _session_info.stream_offset = payload.offset; - _session_info.stream_chunk_transmitted = 0; - _session_info.stream_seq_number = payload.seq_number + 1; - _session_info.stream_target_system_id = 0; // FIXME: _server_component_impl.get_system_id(); + //// Setup for streaming sends + //_session_info.stream_download = true; + //_session_info.stream_offset = payload.offset; + //_session_info.stream_chunk_transmitted = 0; + //_session_info.stream_seq_number = payload.seq_number + 1; + //_session_info.stream_target_system_id = 0; // FIXME: _server_component_impl.get_system_id(); } void MavlinkFtpServer::_work_write(const PayloadHeader& payload, PayloadHeader& response) { - if (payload.session != 0 && _session_info.fd < 0) { + if (payload.session != 0 && !_session_info.ofstream.is_open()) { _reset(); } - if (lseek(_session_info.fd, payload.offset, SEEK_SET) < 0) { - // Unable to see to the specified location + _session_info.ofstream.seekp(payload.offset); + if (_session_info.ifstream.fail()) { response.opcode = Opcode::RSP_NAK; response.size = 1; response.data[0] = ServerResult::ERR_FAIL; + LogWarn() << "Seek failed"; return; } - const int bytes_written = ::write(_session_info.fd, &payload.data[0], payload.size); - - if (bytes_written < 0) { - // Negative return indicates error other than eof + _session_info.ofstream.write(reinterpret_cast(payload.data), payload.size); + if (_session_info.ofstream.fail()) { response.opcode = Opcode::RSP_NAK; response.size = 1; response.data[0] = ServerResult::ERR_FAIL; + LogWarn() << "Write failed"; return; } response.opcode = Opcode::RSP_ACK; response.size = sizeof(uint32_t); - std::memcpy(response.data, &bytes_written, response.size); + std::memcpy(response.data, &payload.size, response.size); } void MavlinkFtpServer::_work_terminate(const PayloadHeader& payload, PayloadHeader& response) @@ -705,10 +721,12 @@ void MavlinkFtpServer::_work_terminate(const PayloadHeader& payload, PayloadHead void MavlinkFtpServer::_reset() { - if (_session_info.fd != -1) { - close(_session_info.fd); - _session_info.fd = -1; - _session_info.stream_download = false; + if (_session_info.ifstream.is_open()) { + _session_info.ifstream.close(); + } + + if (_session_info.ofstream.is_open()) { + _session_info.ofstream.close(); } } @@ -853,29 +871,30 @@ MavlinkFtpServer::_calc_local_file_crc32(const std::string& path, uint32_t& csum return ServerResult::ERR_FAIL_FILE_DOES_NOT_EXIST; } - int fd = ::open(path.c_str(), O_RDONLY); - if (fd < 0) { + std::ifstream ifstream; + ifstream.open(path, std::ios::in | std::ios::binary); + + if (!ifstream.is_open()) { return ServerResult::ERR_FILE_IO_ERROR; } // Read whole file in buffer size chunks Crc32 checksum; char buffer[18392]; - ssize_t bytes_read; do { - bytes_read = ::read(fd, buffer, sizeof(buffer)); + ifstream.read(buffer, sizeof(buffer)); - if (bytes_read < 0) { - int r_errno = errno; - close(fd); - errno = r_errno; + if (ifstream.fail() && !ifstream.eof()) { + ifstream.close(); return ServerResult::ERR_FILE_IO_ERROR; } + auto bytes_read = ifstream.gcount(); checksum.add((uint8_t*)buffer, bytes_read); - } while (bytes_read == sizeof(buffer)); - close(fd); + } while (!ifstream.eof()); + + ifstream.close(); csum = checksum.get(); diff --git a/src/mavsdk/core/mavlink_ftp_server.h b/src/mavsdk/core/mavlink_ftp_server.h index 75a0d47253..533cb1e2b7 100644 --- a/src/mavsdk/core/mavlink_ftp_server.h +++ b/src/mavsdk/core/mavlink_ftp_server.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include @@ -111,13 +110,14 @@ class MavlinkFtpServer { "PayloadHeader size is incorrect."); struct SessionInfo { - int fd{-1}; uint32_t file_size{0}; bool stream_download{false}; uint32_t stream_offset{0}; uint16_t stream_seq_number{0}; uint8_t stream_target_system_id{0}; unsigned stream_chunk_transmitted{0}; + std::ifstream ifstream; + std::ofstream ofstream; }; struct OfstreamWithPath { diff --git a/src/mavsdk/core/tronkko_dirent.h b/src/mavsdk/core/tronkko_dirent.h deleted file mode 100644 index 7db3875d9e..0000000000 --- a/src/mavsdk/core/tronkko_dirent.h +++ /dev/null @@ -1,1154 +0,0 @@ -#pragma once -// Taken from: -// https://github.com/tronkko/dirent/blob/c885633e126a3a949ec0497273ec13e2c03e862c/include/dirent.h - -/* - * Dirent interface for Microsoft Visual Studio - * - * Copyright (C) 1998-2019 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - */ - -/* Hide warnings about unreferenced local functions */ -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wunused-function" -#elif defined(_MSC_VER) -# pragma warning(disable:4505) -#elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wunused-function" -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Indicates that d_type field is available in dirent structure */ -#define _DIRENT_HAVE_D_TYPE - -/* Indicates that d_namlen field is available in dirent structure */ -#define _DIRENT_HAVE_D_NAMLEN - -/* Entries missing from MSVC 6.0 */ -#if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 -#endif - -/* File type and permission flags for stat(), general mask */ -#if !defined(S_IFMT) -# define S_IFMT _S_IFMT -#endif - -/* Directory bit */ -#if !defined(S_IFDIR) -# define S_IFDIR _S_IFDIR -#endif - -/* Character device bit */ -#if !defined(S_IFCHR) -# define S_IFCHR _S_IFCHR -#endif - -/* Pipe bit */ -#if !defined(S_IFFIFO) -# define S_IFFIFO _S_IFFIFO -#endif - -/* Regular file bit */ -#if !defined(S_IFREG) -# define S_IFREG _S_IFREG -#endif - -/* Read permission */ -#if !defined(S_IREAD) -# define S_IREAD _S_IREAD -#endif - -/* Write permission */ -#if !defined(S_IWRITE) -# define S_IWRITE _S_IWRITE -#endif - -/* Execute permission */ -#if !defined(S_IEXEC) -# define S_IEXEC _S_IEXEC -#endif - -/* Pipe */ -#if !defined(S_IFIFO) -# define S_IFIFO _S_IFIFO -#endif - -/* Block device */ -#if !defined(S_IFBLK) -# define S_IFBLK 0 -#endif - -/* Link */ -#if !defined(S_IFLNK) -# define S_IFLNK 0 -#endif - -/* Socket */ -#if !defined(S_IFSOCK) -# define S_IFSOCK 0 -#endif - -/* Read user permission */ -#if !defined(S_IRUSR) -# define S_IRUSR S_IREAD -#endif - -/* Write user permission */ -#if !defined(S_IWUSR) -# define S_IWUSR S_IWRITE -#endif - -/* Execute user permission */ -#if !defined(S_IXUSR) -# define S_IXUSR 0 -#endif - -/* Read group permission */ -#if !defined(S_IRGRP) -# define S_IRGRP 0 -#endif - -/* Write group permission */ -#if !defined(S_IWGRP) -# define S_IWGRP 0 -#endif - -/* Execute group permission */ -#if !defined(S_IXGRP) -# define S_IXGRP 0 -#endif - -/* Read others permission */ -#if !defined(S_IROTH) -# define S_IROTH 0 -#endif - -/* Write others permission */ -#if !defined(S_IWOTH) -# define S_IWOTH 0 -#endif - -/* Execute others permission */ -#if !defined(S_IXOTH) -# define S_IXOTH 0 -#endif - -/* Maximum length of file name */ -#if !defined(PATH_MAX) -# define PATH_MAX MAX_PATH -#endif -#if !defined(FILENAME_MAX) -# define FILENAME_MAX MAX_PATH -#endif -#if !defined(NAME_MAX) -# define NAME_MAX FILENAME_MAX -#endif - -/* File type flags for d_type */ -#define DT_UNKNOWN 0 -#define DT_REG S_IFREG -#define DT_DIR S_IFDIR -#define DT_FIFO S_IFIFO -#define DT_SOCK S_IFSOCK -#define DT_CHR S_IFCHR -#define DT_BLK S_IFBLK -#define DT_LNK S_IFLNK - -/* Macros for converting between st_mode and d_type */ -#define IFTODT(mode) ((mode) & S_IFMT) -#define DTTOIF(type) (type) - -/* - * File type macros. Note that block devices, sockets and links cannot be - * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are - * only defined for compatibility. These macros should always return false - * on Windows. - */ -#if !defined(S_ISFIFO) -# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) -#endif -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#endif -#if !defined(S_ISREG) -# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif -#if !defined(S_ISLNK) -# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#endif -#if !defined(S_ISSOCK) -# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) -#endif -#if !defined(S_ISCHR) -# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) -#endif -#if !defined(S_ISBLK) -# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) -#endif - -/* Return the exact length of the file name without zero terminator */ -#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) - -/* Return the maximum size of a file name */ -#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Wide-character version */ -struct _wdirent { - /* Always zero */ - long d_ino; - - /* File position within stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - wchar_t d_name[PATH_MAX+1]; -}; -typedef struct _wdirent _wdirent; - -struct _WDIR { - /* Current directory entry */ - struct _wdirent ent; - - /* Private file data */ - WIN32_FIND_DATAW data; - - /* True if data is valid */ - int cached; - - /* Win32 search handle */ - HANDLE handle; - - /* Initial directory name */ - wchar_t *patt; -}; -typedef struct _WDIR _WDIR; - -/* Multi-byte character version */ -struct dirent { - /* Always zero */ - long d_ino; - - /* File position within stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - char d_name[PATH_MAX+1]; -}; -typedef struct dirent dirent; - -struct DIR { - struct dirent ent; - struct _WDIR *wdirp; -}; -typedef struct DIR DIR; - - -/* Dirent functions */ -static DIR *opendir (const char *dirname); -static _WDIR *_wopendir (const wchar_t *dirname); - -static struct dirent *readdir (DIR *dirp); -static struct _wdirent *_wreaddir (_WDIR *dirp); - -static int readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result); -static int _wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); - -static int closedir (DIR *dirp); -static int _wclosedir (_WDIR *dirp); - -static void rewinddir (DIR* dirp); -static void _wrewinddir (_WDIR* dirp); - -static int scandir (const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)); - -static int alphasort (const struct dirent **a, const struct dirent **b); - -static int versionsort (const struct dirent **a, const struct dirent **b); - - -/* For compatibility with Symbian */ -#define wdirent _wdirent -#define WDIR _WDIR -#define wopendir _wopendir -#define wreaddir _wreaddir -#define wclosedir _wclosedir -#define wrewinddir _wrewinddir - - -/* Internal utility functions */ -static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); -static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); - -static int dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count); - -static int dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, - const wchar_t *wcstr, - size_t count); - -static void dirent_set_errno (int error); - - -/* - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ -static _WDIR* -_wopendir( - const wchar_t *dirname) -{ - _WDIR *dirp; - DWORD n; - wchar_t *p; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno (ENOENT); - return NULL; - } - - /* Allocate new _WDIR structure */ - dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); - if (!dirp) { - return NULL; - } - - /* Reset _WDIR structure */ - dirp->handle = INVALID_HANDLE_VALUE; - dirp->patt = NULL; - dirp->cached = 0; - - /* - * Compute the length of full path plus zero terminator - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - n = GetFullPathNameW (dirname, 0, NULL, NULL); -#else - /* WinRT */ - n = wcslen (dirname); -#endif - - /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); - if (dirp->patt == NULL) { - goto exit_closedir; - } - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly even when current - * working directory is changed between opendir() and rewinddir(). - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - n = GetFullPathNameW (dirname, n, dirp->patt, NULL); - if (n <= 0) { - goto exit_closedir; - } -#else - /* WinRT */ - wcsncpy_s (dirp->patt, n+1, dirname, n); -#endif - - /* Append search pattern \* to the directory name */ - p = dirp->patt + n; - switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; - } - *p++ = '*'; - *p = '\0'; - - /* Open directory stream and retrieve the first entry */ - if (!dirent_first (dirp)) { - goto exit_closedir; - } - - /* Success */ - return dirp; - - /* Failure */ -exit_closedir: - _wclosedir (dirp); - return NULL; -} - -/* - * Read next directory entry. - * - * Returns pointer to static directory entry which may be overwritten by - * subsequent calls to _wreaddir(). - */ -static struct _wdirent* -_wreaddir( - _WDIR *dirp) -{ - struct _wdirent *entry; - - /* - * Read directory entry to buffer. We can safely ignore the return value - * as entry will be set to NULL in case of error. - */ - (void) _wreaddir_r (dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry. - * - * Returns zero on success. If end of directory stream is reached, then sets - * result to NULL and returns zero. - */ -static int -_wreaddir_r( - _WDIR *dirp, - struct _wdirent *entry, - struct _wdirent **result) -{ - WIN32_FIND_DATAW *datap; - - /* Read next directory entry */ - datap = dirent_next (dirp); - if (datap) { - size_t n; - DWORD attr; - - /* - * Copy file name as wide-character string. If the file name is too - * long to fit in to the destination buffer, then truncate file name - * to PATH_MAX characters and zero-terminate the buffer. - */ - n = 0; - while (n < PATH_MAX && datap->cFileName[n] != 0) { - entry->d_name[n] = datap->cFileName[n]; - n++; - } - entry->d_name[n] = 0; - - /* Length of file name excluding zero terminator */ - entry->d_namlen = n; - - /* File type */ - attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - entry->d_type = DT_CHR; - } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - entry->d_type = DT_DIR; - } else { - entry->d_type = DT_REG; - } - - /* Reset dummy fields */ - entry->d_ino = 0; - entry->d_off = 0; - entry->d_reclen = sizeof (struct _wdirent); - - /* Set result address */ - *result = entry; - - } else { - - /* Return NULL to indicate end of directory */ - *result = NULL; - - } - - return /*OK*/0; -} - -/* - * Close directory stream opened by opendir() function. This invalidates the - * DIR structure as well as any directory entry read previously by - * _wreaddir(). - */ -static int -_wclosedir( - _WDIR *dirp) -{ - int ok; - if (dirp) { - - /* Release search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->handle); - } - - /* Release search pattern */ - free (dirp->patt); - - /* Release directory structure */ - free (dirp); - ok = /*success*/0; - - } else { - - /* Invalid directory stream */ - dirent_set_errno (EBADF); - ok = /*failure*/-1; - - } - return ok; -} - -/* - * Rewind directory stream such that _wreaddir() returns the very first - * file name again. - */ -static void -_wrewinddir( - _WDIR* dirp) -{ - if (dirp) { - /* Release existing search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->handle); - } - - /* Open new search handle */ - dirent_first (dirp); - } -} - -/* Get first directory entry (internal) */ -static WIN32_FIND_DATAW* -dirent_first( - _WDIR *dirp) -{ - WIN32_FIND_DATAW *datap; - DWORD error; - - /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileExW( - dirp->patt, FindExInfoStandard, &dirp->data, - FindExSearchNameMatch, NULL, 0); - if (dirp->handle != INVALID_HANDLE_VALUE) { - - /* a directory entry is now waiting in memory */ - datap = &dirp->data; - dirp->cached = 1; - - } else { - - /* Failed to open directory: no directory entry in memory */ - dirp->cached = 0; - datap = NULL; - - /* Set error code */ - error = GetLastError (); - switch (error) { - case ERROR_ACCESS_DENIED: - /* No read access to directory */ - dirent_set_errno (EACCES); - break; - - case ERROR_DIRECTORY: - /* Directory name is invalid */ - dirent_set_errno (ENOTDIR); - break; - - case ERROR_PATH_NOT_FOUND: - default: - /* Cannot find the file */ - dirent_set_errno (ENOENT); - } - - } - return datap; -} - -/* - * Get next directory entry (internal). - * - * Returns - */ -static WIN32_FIND_DATAW* -dirent_next( - _WDIR *dirp) -{ - WIN32_FIND_DATAW *p; - - /* Get next directory entry */ - if (dirp->cached != 0) { - - /* A valid directory entry already in memory */ - p = &dirp->data; - dirp->cached = 0; - - } else if (dirp->handle != INVALID_HANDLE_VALUE) { - - /* Get the next directory entry from stream */ - if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { - /* Got a file */ - p = &dirp->data; - } else { - /* The very last entry has been processed or an error occurred */ - FindClose (dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - p = NULL; - } - - } else { - - /* End of directory stream reached */ - p = NULL; - - } - - return p; -} - -/* - * Open directory stream using plain old C-string. - */ -static DIR* -opendir( - const char *dirname) -{ - struct DIR *dirp; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno (ENOENT); - return NULL; - } - - /* Allocate memory for DIR structure */ - dirp = (DIR*) malloc (sizeof (struct DIR)); - if (!dirp) { - return NULL; - } - { - int error; - wchar_t wname[PATH_MAX + 1]; - size_t n; - - /* Convert directory name to wide-character string */ - error = dirent_mbstowcs_s( - &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); - if (error) { - /* - * Cannot convert file name to wide-character string. This - * occurs if the string contains invalid multi-byte sequences or - * the output buffer is too small to contain the resulting - * string. - */ - goto exit_free; - } - - - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir (wname); - if (!dirp->wdirp) { - goto exit_free; - } - - } - - /* Success */ - return dirp; - - /* Failure */ -exit_free: - free (dirp); - return NULL; -} - -/* - * Read next directory entry. - */ -static struct dirent* -readdir( - DIR *dirp) -{ - struct dirent *entry; - - /* - * Read directory entry to buffer. We can safely ignore the return value - * as entry will be set to NULL in case of error. - */ - (void) readdir_r (dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry into called-allocated buffer. - * - * Returns zero on success. If the end of directory stream is reached, then - * sets result to NULL and returns zero. - */ -static int -readdir_r( - DIR *dirp, - struct dirent *entry, - struct dirent **result) -{ - WIN32_FIND_DATAW *datap; - - /* Read next directory entry */ - datap = dirent_next (dirp->wdirp); - if (datap) { - size_t n; - int error; - - /* Attempt to convert file name to multi-byte string */ - error = dirent_wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); - - /* - * If the file name cannot be represented by a multi-byte string, - * then attempt to use old 8+3 file name. This allows traditional - * Unix-code to access some file names despite of unicode - * characters, although file names may seem unfamiliar to the user. - * - * Be ware that the code below cannot come up with a short file - * name unless the file system provides one. At least - * VirtualBox shared folders fail to do this. - */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = dirent_wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cAlternateFileName, PATH_MAX + 1); - } - - if (!error) { - DWORD attr; - - /* Length of file name excluding zero terminator */ - entry->d_namlen = n - 1; - - /* File attributes */ - attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - entry->d_type = DT_CHR; - } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - entry->d_type = DT_DIR; - } else { - entry->d_type = DT_REG; - } - - /* Reset dummy fields */ - entry->d_ino = 0; - entry->d_off = 0; - entry->d_reclen = sizeof (struct dirent); - - } else { - - /* - * Cannot convert file name to multi-byte string so construct - * an erroneous directory entry and return that. Note that - * we cannot return NULL as that would stop the processing - * of directory entries completely. - */ - entry->d_name[0] = '?'; - entry->d_name[1] = '\0'; - entry->d_namlen = 1; - entry->d_type = DT_UNKNOWN; - entry->d_ino = 0; - entry->d_off = -1; - entry->d_reclen = 0; - - } - - /* Return pointer to directory entry */ - *result = entry; - - } else { - - /* No more directory entries */ - *result = NULL; - - } - - return /*OK*/0; -} - -/* - * Close directory stream. - */ -static int -closedir( - DIR *dirp) -{ - int ok; - if (dirp) { - - /* Close wide-character directory stream */ - ok = _wclosedir (dirp->wdirp); - dirp->wdirp = NULL; - - /* Release multi-byte character version */ - free (dirp); - - } else { - - /* Invalid directory stream */ - dirent_set_errno (EBADF); - ok = /*failure*/-1; - - } - return ok; -} - -/* - * Rewind directory stream to beginning. - */ -static void -rewinddir( - DIR* dirp) -{ - /* Rewind wide-character string directory stream */ - _wrewinddir (dirp->wdirp); -} - -/* - * Scan directory for entries. - */ -static int -scandir( - const char *dirname, - struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)) -{ - struct dirent **files = NULL; - size_t size = 0; - size_t allocated = 0; - const size_t init_size = 1; - DIR *dir = NULL; - struct dirent *entry; - struct dirent *tmp = NULL; - size_t i; - int result = 0; - - /* Open directory stream */ - dir = opendir (dirname); - if (dir) { - - /* Read directory entries to memory */ - while (1) { - - /* Enlarge pointer table to make room for another pointer */ - if (size >= allocated) { - void *p; - size_t num_entries; - - /* Compute number of entries in the enlarged pointer table */ - if (size < init_size) { - /* Allocate initial pointer table */ - num_entries = init_size; - } else { - /* Double the size */ - num_entries = size * 2; - } - - /* Allocate first pointer table or enlarge existing table */ - p = realloc (files, sizeof (void*) * num_entries); - if (p != NULL) { - /* Got the memory */ - files = (dirent**) p; - allocated = num_entries; - } else { - /* Out of memory */ - result = -1; - break; - } - - } - - /* Allocate room for temporary directory entry */ - if (tmp == NULL) { - tmp = (struct dirent*) malloc (sizeof (struct dirent)); - if (tmp == NULL) { - /* Cannot allocate temporary directory entry */ - result = -1; - break; - } - } - - /* Read directory entry to temporary area */ - if (readdir_r (dir, tmp, &entry) == /*OK*/0) { - - /* Did we get an entry? */ - if (entry != NULL) { - int pass; - - /* Determine whether to include the entry in result */ - if (filter) { - /* Let the filter function decide */ - pass = filter (tmp); - } else { - /* No filter function, include everything */ - pass = 1; - } - - if (pass) { - /* Store the temporary entry to pointer table */ - files[size++] = tmp; - tmp = NULL; - - /* Keep up with the number of files */ - result++; - } - - } else { - - /* - * End of directory stream reached => sort entries and - * exit. - */ - qsort (files, size, sizeof (void*), - (int (*) (const void*, const void*)) compare); - break; - - } - - } else { - /* Error reading directory entry */ - result = /*Error*/ -1; - break; - } - - } - - } else { - /* Cannot open directory */ - result = /*Error*/ -1; - } - - /* Release temporary directory entry */ - free (tmp); - - /* Release allocated memory on error */ - if (result < 0) { - for (i = 0; i < size; i++) { - free (files[i]); - } - free (files); - files = NULL; - } - - /* Close directory stream */ - if (dir) { - closedir (dir); - } - - /* Pass pointer table to caller */ - if (namelist) { - *namelist = files; - } - return result; -} - -/* Alphabetical sorting */ -static int -alphasort( - const struct dirent **a, const struct dirent **b) -{ - return strcoll ((*a)->d_name, (*b)->d_name); -} - -/* Sort versions */ -static int -versionsort( - const struct dirent **a, const struct dirent **b) -{ - /* FIXME: implement strverscmp and use that */ - return alphasort (a, b); -} - -/* Convert multi-byte string to wide character string */ -static int -dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count) -{ - int error; - -#if defined(_MSC_VER) && _MSC_VER >= 1400 - - /* Microsoft Visual Studio 2005 or later */ - error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); - -#else - - /* Older Visual Studio or non-Microsoft compiler */ - size_t n; - - /* Convert to wide-character string (or count characters) */ - n = mbstowcs (wcstr, mbstr, sizeInWords); - if (!wcstr || n < count) { - - /* Zero-terminate output buffer */ - if (wcstr && sizeInWords) { - if (n >= sizeInWords) { - n = sizeInWords - 1; - } - wcstr[n] = 0; - } - - /* Length of resulting multi-byte string WITH zero terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - error = 0; - - } else { - - /* Could not convert string */ - error = 1; - - } - -#endif - return error; -} - -/* Convert wide-character string to multi-byte string */ -static int -dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, /* max size of mbstr */ - const wchar_t *wcstr, - size_t count) -{ - int error; - -#if defined(_MSC_VER) && _MSC_VER >= 1400 - - /* Microsoft Visual Studio 2005 or later */ - error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); - -#else - - /* Older Visual Studio or non-Microsoft compiler */ - size_t n; - - /* Convert to multi-byte string (or count the number of bytes needed) */ - n = wcstombs (mbstr, wcstr, sizeInBytes); - if (!mbstr || n < count) { - - /* Zero-terminate output buffer */ - if (mbstr && sizeInBytes) { - if (n >= sizeInBytes) { - n = sizeInBytes - 1; - } - mbstr[n] = '\0'; - } - - /* Length of resulting multi-bytes string WITH zero-terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - error = 0; - - } else { - - /* Cannot convert string */ - error = 1; - - } - -#endif - return error; -} - -/* Set errno variable */ -static void -dirent_set_errno( - int error) -{ -#if defined(_MSC_VER) && _MSC_VER >= 1400 - - /* Microsoft Visual Studio 2005 and later */ - _set_errno (error); - -#else - - /* Non-Microsoft compiler or older Microsoft compiler */ - errno = error; - -#endif -} - - -#ifdef __cplusplus -} -#endif diff --git a/src/mavsdk/plugins/log_files/log_files_impl.cpp b/src/mavsdk/plugins/log_files/log_files_impl.cpp index 013eaa9a37..de53dc698a 100644 --- a/src/mavsdk/plugins/log_files/log_files_impl.cpp +++ b/src/mavsdk/plugins/log_files/log_files_impl.cpp @@ -1,6 +1,5 @@ #include "log_files_impl.h" #include "mavsdk_impl.h" -#include "filesystem_include.h" #include "unused.h" #include