mirror of
https://github.com/avast/retdec.git
synced 2024-11-23 04:49:53 +00:00
utils: replace our filesystem_path with std::filesystem (#806)
* utils: replace our filesystem_path with std::filesystem * .travis.yml: update xcode11 -> xcode12 * README: bump macOS to 10.15, add note about filesystem lib on GCC 7 * fix windows-specific use of filesystem library * travis.yml: try to use xcode 11.4 instead of 12, ccache doesn't work in 12 * .travis.yml: remove macOS build. After xcode update, ccache either dows not work, or it does not help enough to finish the build in time limit. I.e. macOS build always timeouts and therefore we cannot use it.
This commit is contained in:
parent
f5b7c71921
commit
e72f74eb06
17
.travis.yml
17
.travis.yml
@ -25,30 +25,15 @@ matrix:
|
||||
# e.g. retdec/tests/utils/string_tests.cpp:276:2: error: stray '\' in program
|
||||
- CCACHE_CPP2=true
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode11.2
|
||||
env:
|
||||
- MATRIX_EVAL="NPROC=$(sysctl -n hw.physicalcpu)"
|
||||
- CCACHE_CPP2=true
|
||||
|
||||
install:
|
||||
# ccache is not installed on OS X.
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install ccache; fi
|
||||
# install for os x the gnu time library
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install gnu-time; fi
|
||||
# install for os x the openssl library
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install openssl@1.1; export OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1; fi
|
||||
|
||||
before_script:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
# We need to add ccache before everything else into PATH.
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi
|
||||
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
# We use "-O0" to speed up the build.
|
||||
# "-O0" causes segfaults in LLVM if we do not use "-DNDEBUG" as well.
|
||||
- cmake -DCMAKE_CXX_FLAGS_RELEASE="-O0 -DNDEBUG" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DRETDEC_COMPILE_YARA=OFF ..
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cmake -DCMAKE_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/ .. ; fi
|
||||
- time make install -j $NPROC
|
||||
# Check that install is movable and that it does not need the build directory.
|
||||
- mv install ../retdec-install
|
||||
|
@ -7,6 +7,7 @@
|
||||
* Enhancement: Improved detection of many packers/installers/compilers in `retdec-fileinfo`, including Armadillo ([#733](https://github.com/avast/retdec/pull/733)), VMProtect ([#734](https://github.com/avast/retdec/pull/734), [#778](https://github.com/avast/retdec/pull/778)), Petite ([#735](https://github.com/avast/retdec/pull/735)), Enigma ([#741](https://github.com/avast/retdec/pull/741)), ASPack ([#743](https://github.com/avast/retdec/pull/743)), Eziriz ([#746](https://github.com/avast/retdec/pull/746)), PyInstaller ([#748](https://github.com/avast/retdec/pull/748)), Astrum InstallWizard ([#753](https://github.com/avast/retdec/pull/753)), AutoHotKey ([#756](https://github.com/avast/retdec/pull/756)), AutoIt ([#757](https://github.com/avast/retdec/pull/757)), BAT to PE-EXE script compilers ([#761](https://github.com/avast/retdec/pull/761)), Bero ([#764](https://github.com/avast/retdec/pull/764)), CExe ([#781](https://github.com/avast/retdec/pull/781)), and other improvements ([#804](https://github.com/avast/retdec/pull/804)).
|
||||
* Enhancement: Enable .NET module in RetDec's YARA ([#747](https://github.com/avast/retdec/issues/747)).
|
||||
* Enhancement: Require OpenSSL as a prerequisite. It is no longer built by RetDec ([#807](https://github.com/avast/retdec/pull/807)).
|
||||
* Enhancement: Replace RetDec's `FilesystemPath` implementation with C++ Filesystem library ([#806](https://github.com/avast/retdec/pull/806)).
|
||||
* Fix: Fixed build on some systems by adding missing includes of `<limits>` into `retdec-fileinfo` ([#745](https://github.com/avast/retdec/pull/745)).
|
||||
* Fix: Fixed two type errors in `scripts/retdec-archive-decompiler.py` ([#759](https://github.com/avast/retdec/pull/759)).
|
||||
|
||||
|
@ -183,7 +183,7 @@ sudo pacman --needed -S base-devel cmake git openssl python3 autoconf automake l
|
||||
|
||||
Packages should be preferably installed via [Homebrew](https://brew.sh).
|
||||
|
||||
* macOS >= 10.14
|
||||
* macOS >= 10.15
|
||||
* Full Xcode installation ([including command-line tools](https://github.com/frida/frida/issues/338#issuecomment-426777849), see [#425](https://github.com/avast/retdec/issues/425) and [#433](https://github.com/avast/retdec/issues/433))
|
||||
* [CMake](https://cmake.org/) (version >= 3.6)
|
||||
* [Git](https://git-scm.com/)
|
||||
@ -219,6 +219,8 @@ Note: Although RetDec now supports a system-wide installation ([#94](https://git
|
||||
* `cmake .. -DCMAKE_INSTALL_PREFIX=<path>`
|
||||
* `make -jN` (`N` is the number of processes to use for parallel build, typically number of cores + 1 gives fastest compilation time)
|
||||
* `make install`
|
||||
* _Note_: RetDec requires [filesystem](https://en.cppreference.com/w/cpp/filesystem) library. CMake will try to find the library in the system but on GCC 7 it might fail to do so. In that case you must specify a path to the library:
|
||||
* `-DCMAKE_LIBRARY_PATH=${PATH_TO_FILESTSTEM_DIR}`, e.g. on GCC 7 `stdc++fs` is in `-DCMAKE_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/`.
|
||||
* Windows:
|
||||
* Open a command prompt (e.g. `cmd.exe`)
|
||||
* `cd retdec`
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <llvm/IR/Module.h>
|
||||
|
||||
#include "retdec/common/address.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
|
||||
namespace retdec {
|
||||
namespace bin2llvmir {
|
||||
@ -169,7 +169,7 @@ class Config
|
||||
// Other
|
||||
//
|
||||
llvm::GlobalVariable* getGlobalDummy();
|
||||
utils::FilesystemPath getOutputDirectory();
|
||||
fs::path getOutputDirectory();
|
||||
bool getCryptoPattern(
|
||||
retdec::common::Address addr,
|
||||
std::string& name,
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
|
||||
namespace retdec {
|
||||
namespace bin2llvmir {
|
||||
@ -48,11 +48,11 @@ std::string llvmObjToString(const llvm::Module* t);
|
||||
|
||||
void dumpModuleToFile(
|
||||
const llvm::Module* m,
|
||||
utils::FilesystemPath dirName,
|
||||
fs::path dirName,
|
||||
const std::string& fileName = "");
|
||||
void dumpControFlowToJson(
|
||||
llvm::Module* m,
|
||||
utils::FilesystemPath dirName,
|
||||
fs::path dirName,
|
||||
const std::string& fileName = "control-flow.json");
|
||||
|
||||
} // namespace bin2llvmir
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef RETDEC_CPDETECT_CPDETECT_H
|
||||
#define RETDEC_CPDETECT_CPDETECT_H
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/utils/non_copyable.h"
|
||||
#include "retdec/cpdetect/cptypes.h"
|
||||
#include "retdec/cpdetect/errors.h"
|
||||
@ -47,7 +47,7 @@ class CompilerDetector : private retdec::utils::NonCopyable
|
||||
|
||||
protected:
|
||||
void populateInternalPaths(
|
||||
const retdec::utils::FilesystemPath& dir,
|
||||
const fs::path& dir,
|
||||
const std::set<std::string>& formats,
|
||||
const std::set<std::string>& archs);
|
||||
|
||||
@ -62,7 +62,7 @@ class CompilerDetector : private retdec::utils::NonCopyable
|
||||
/// internal rule database files
|
||||
std::vector<std::string> internalPaths;
|
||||
/// path to shared folder
|
||||
retdec::utils::FilesystemPath pathToShared;
|
||||
fs::path pathToShared;
|
||||
/// external database file suffixes
|
||||
std::set<std::string> externalSuffixes;
|
||||
|
||||
|
@ -7,13 +7,13 @@
|
||||
#ifndef RETDEC_UTILS_BINARY_PATH_H
|
||||
#define RETDEC_UTILS_BINARY_PATH_H
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
|
||||
namespace retdec {
|
||||
namespace utils {
|
||||
|
||||
FilesystemPath getThisBinaryPath();
|
||||
FilesystemPath getThisBinaryDirectoryPath();
|
||||
fs::path getThisBinaryPath();
|
||||
fs::path getThisBinaryDirectoryPath();
|
||||
|
||||
} // namespace utils
|
||||
} // namespace retdec
|
||||
|
23
include/retdec/utils/filesystem.h
Normal file
23
include/retdec/utils/filesystem.h
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file include/retdec/utils/filesystem.h
|
||||
* @brief Wrapper for conditional include of C++17 filesystem feature.
|
||||
* @copyright (c) 2020 Avast Software, licensed under the MIT license
|
||||
*/
|
||||
|
||||
#ifndef RETDEC_UTILS_FILESYSTEM_H
|
||||
#define RETDEC_UTILS_FILESYSTEM_H
|
||||
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
#else
|
||||
#error "Compiler does not have C++17 filesystem feature."
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,181 +0,0 @@
|
||||
/**
|
||||
* @file include/retdec/utils/filesystem_path.h
|
||||
* @brief FilesystemPath class implementation for unified work with filepaths.
|
||||
* @copyright (c) 2017 Avast Software, licensed under the MIT license
|
||||
*/
|
||||
|
||||
#ifndef RETDEC_UTILS_FILESYSTEM_PATH_H
|
||||
#define RETDEC_UTILS_FILESYSTEM_PATH_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "retdec/utils/os.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
namespace retdec {
|
||||
namespace utils {
|
||||
|
||||
class FilesystemPathImpl;
|
||||
|
||||
/**
|
||||
* @brief Abstraction of a filesystem path and its subpaths.
|
||||
*
|
||||
* FilesystemPath represents a path in a user filesystem. It also
|
||||
* supports iterating over the subpaths in the specified path.
|
||||
* Loading of subpaths is performed through lazy loading. Subpaths are
|
||||
* loaded only if they are requested through begin() or end() call.
|
||||
*/
|
||||
class FilesystemPath
|
||||
{
|
||||
public:
|
||||
FilesystemPath() = delete;
|
||||
FilesystemPath(const std::string& path);
|
||||
FilesystemPath(const FilesystemPath& fspath);
|
||||
~FilesystemPath();
|
||||
|
||||
std::string getPath() const;
|
||||
std::string getParentPath() const;
|
||||
std::string getAbsolutePath() const;
|
||||
bool exists() const;
|
||||
bool isDirectory() const;
|
||||
bool isFile() const;
|
||||
bool isAbsolute() const;
|
||||
bool isRelative() const;
|
||||
|
||||
void append(const std::string& path);
|
||||
|
||||
/**
|
||||
* Iterator represent the node for subpath traversing.
|
||||
*/
|
||||
template <
|
||||
typename Category,
|
||||
typename Type,
|
||||
typename Reference = Type&,
|
||||
typename Pointer = Type*,
|
||||
typename Distance = std::ptrdiff_t
|
||||
>
|
||||
class iterator_impl
|
||||
{
|
||||
public:
|
||||
using difference_type = Distance;
|
||||
using value_type = Type;
|
||||
using reference = Reference;
|
||||
using pointer = Pointer;
|
||||
using iterator_category = Category;
|
||||
|
||||
iterator_impl(const FilesystemPath* root, std::uint64_t index = 0) : _root(root), _index(index) {} ///< Constructor.
|
||||
|
||||
iterator_impl() = default;
|
||||
iterator_impl(const iterator_impl& itr) = default;
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
*
|
||||
* @param rhs Right-hand side of the expression.
|
||||
*
|
||||
* @return Copied right-hand side assigned to iterator.
|
||||
*/
|
||||
iterator_impl& operator=(const iterator_impl& rhs)
|
||||
{
|
||||
_root = rhs._root;
|
||||
_index = rhs._index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move iterator to the next element. Prefix increment.
|
||||
*
|
||||
* @return The same iterator, while poiting to the next element.
|
||||
*/
|
||||
iterator_impl& operator++()
|
||||
{
|
||||
++_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move iterator to the next element. Postfix increment.
|
||||
*
|
||||
* @return The iterator poiniting to the old element.
|
||||
*/
|
||||
iterator_impl operator++(int)
|
||||
{
|
||||
iterator_impl tmp(*this);
|
||||
++_index;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compres two iterators. Two iterators are same if they have the same root
|
||||
* and they are pointing to the same element in the subpaths.
|
||||
*
|
||||
* @return True if iterators are same, otherwise false.
|
||||
*/
|
||||
bool operator==(const iterator_impl& rhs) const
|
||||
{
|
||||
return ((_root == rhs._root) && (_index == rhs._index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compres two iterators. Two iterators are same if they have the same root
|
||||
* and they are pointing to the same element in the subpaths.
|
||||
*
|
||||
* @return True if iterators are not same, otherwise false.
|
||||
*/
|
||||
bool operator!=(const iterator_impl& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the FilesystemPath pointed by iterator.
|
||||
*
|
||||
* @return FilesystemPath object.
|
||||
*/
|
||||
value_type operator*() const
|
||||
{
|
||||
return _root->_subpaths[_index].get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the FilesystemPath pointed by iterator.
|
||||
*
|
||||
* @return FilesystemPath object.
|
||||
*/
|
||||
value_type operator->() const
|
||||
{
|
||||
return _root->_subpaths[_index].get();
|
||||
}
|
||||
|
||||
private:
|
||||
const FilesystemPath* _root; ///< Root path of the iterator.
|
||||
std::uint64_t _index; ///< Index of the subpaths in the root path.
|
||||
};
|
||||
|
||||
using iterator = iterator_impl<std::input_iterator_tag, FilesystemPath*>;
|
||||
using const_iterator = iterator_impl<std::input_iterator_tag, const FilesystemPath*>;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
static char separator();
|
||||
|
||||
private:
|
||||
void loadSubpaths() const;
|
||||
|
||||
std::unique_ptr<FilesystemPathImpl> _impl; ///< Platform specific implementations.
|
||||
|
||||
mutable bool _subpathsLoaded; ///< Internal status for lazy loading.
|
||||
mutable std::vector<std::unique_ptr<FilesystemPath>> _subpaths; ///< Subpaths in the specified path.
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
} // namespace retdec
|
||||
|
||||
#endif
|
@ -13,7 +13,7 @@
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/prettywriter.h>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/ar-extractor/archive_wrapper.h"
|
||||
|
||||
@ -252,7 +252,7 @@ bool ArchiveWrapper::extract(
|
||||
const std::string &directory) const
|
||||
{
|
||||
// Check if target directory exists if string not empty.
|
||||
if (!directory.empty() && !FilesystemPath(directory).isDirectory()) {
|
||||
if (!directory.empty() && !fs::is_directory(directory)) {
|
||||
errorMessage = "Invalid target directory";
|
||||
return false;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/prettywriter.h>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/ar-extractor/archive_wrapper.h"
|
||||
#include "retdec/ar-extractor/detection.h"
|
||||
|
||||
@ -275,7 +275,7 @@ int processArguments(
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (FilesystemPath(arg).isFile()) {
|
||||
if (fs::is_regular_file(arg)) {
|
||||
if (inputArchive.empty()) {
|
||||
inputArchive = arg;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ bool Decoder::run()
|
||||
|
||||
decode();
|
||||
|
||||
if (debug_enabled && _config->getOutputDirectory().exists())
|
||||
if (debug_enabled && fs::exists(_config->getOutputDirectory()))
|
||||
{
|
||||
dumpModuleToFile(_module, _config->getOutputDirectory());
|
||||
}
|
||||
@ -121,7 +121,7 @@ bool Decoder::run()
|
||||
patternsRecognize();
|
||||
finalizePseudoCalls();
|
||||
|
||||
if (debug_enabled && _config->getOutputDirectory().exists())
|
||||
if (debug_enabled && fs::exists(_config->getOutputDirectory()))
|
||||
{
|
||||
dumpControFlowToJson(_module, _config->getOutputDirectory());
|
||||
dumpModuleToFile(_module, _config->getOutputDirectory());
|
||||
@ -129,7 +129,7 @@ bool Decoder::run()
|
||||
|
||||
initConfigFunctions();
|
||||
|
||||
if (debug_enabled && _config->getOutputDirectory().exists())
|
||||
if (debug_enabled && fs::exists(_config->getOutputDirectory()))
|
||||
{
|
||||
dumpModuleToFile(_module, _config->getOutputDirectory());
|
||||
}
|
||||
|
@ -600,7 +600,7 @@ llvm::Function* Decoder::splitFunctionOn(
|
||||
for (auto* s : successors(&b))
|
||||
{
|
||||
if (b.getParent() != s->getParent()
|
||||
&& _config->getOutputDirectory().exists())
|
||||
&& fs::exists(_config->getOutputDirectory()))
|
||||
{
|
||||
dumpModuleToFile(_module, _config->getOutputDirectory());
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ DumpModule::DumpModule() :
|
||||
bool DumpModule::runOnModule(Module& M)
|
||||
{
|
||||
auto* c = ConfigProvider::getConfig(&M);
|
||||
if (c && c->getOutputDirectory().exists())
|
||||
if (c && fs::exists(c->getOutputDirectory()))
|
||||
{
|
||||
dumpModuleToFile(&M, c->getOutputDirectory());
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "retdec/bin2llvmir/optimizations/param_return/collector/collector.h"
|
||||
#include "retdec/bin2llvmir/optimizations/param_return/collector/pic32.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace llvm;
|
||||
|
||||
namespace retdec {
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "retdec/bin2llvmir/optimizations/param_return/collector/pic32.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace llvm;
|
||||
|
||||
namespace retdec {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "retdec/bin2llvmir/optimizations/param_return/filter/filter.h"
|
||||
#include "retdec/bin2llvmir/optimizations/param_return/filter/ms_x64.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace llvm;
|
||||
|
||||
namespace retdec {
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include "retdec/bin2llvmir/optimizations/param_return/filter/ms_x64.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace llvm;
|
||||
|
||||
namespace retdec {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "retdec/bin2llvmir/providers/lti.h"
|
||||
#include "retdec/bin2llvmir/providers/names.h"
|
||||
#include "retdec/cpdetect/cpdetect.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/yaracpp/yara_detector.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <llvm/IR/Instruction.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/utils/time.h"
|
||||
#include "retdec/bin2llvmir/optimizations/writer_dsm/writer_dsm.h"
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <llvm/IR/InstIterator.h>
|
||||
|
||||
#include "retdec/utils/container.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/bin2llvmir/providers/asm_instruction.h"
|
||||
#include "retdec/bin2llvmir/providers/names.h"
|
||||
#include "retdec/bin2llvmir/utils/debug.h"
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include "retdec/bin2llvmir/providers/demangler.h"
|
||||
#include "retdec/bin2llvmir/utils/debug.h"
|
||||
#include "retdec/bin2llvmir/utils/llvm.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace llvm;
|
||||
|
||||
namespace retdec {
|
||||
@ -456,10 +456,10 @@ llvm::GlobalVariable* Config::getGlobalDummy()
|
||||
return _globalDummy;
|
||||
}
|
||||
|
||||
utils::FilesystemPath Config::getOutputDirectory()
|
||||
fs::path Config::getOutputDirectory()
|
||||
{
|
||||
FilesystemPath fsp(getConfig().parameters.getOutputFile());
|
||||
return fsp.getParentPath();
|
||||
fs::path fsp(getConfig().parameters.getOutputFile());
|
||||
return fs::canonical(fsp).parent_path();
|
||||
}
|
||||
|
||||
void Config::setLlvmCallPseudoFunction(llvm::Function* f)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "retdec/bin2llvmir/providers/lti.h"
|
||||
#include "retdec/bin2llvmir/utils/ctypes2llvm.h"
|
||||
#include "retdec/ctypes/ctypes.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -54,7 +54,7 @@ std::string llvmObjToString(const llvm::Module* t)
|
||||
|
||||
void dumpModuleToFile(
|
||||
const llvm::Module* m,
|
||||
utils::FilesystemPath dirName,
|
||||
fs::path dirName,
|
||||
const std::string& fileName)
|
||||
{
|
||||
static unsigned cntr = 0;
|
||||
@ -64,7 +64,7 @@ void dumpModuleToFile(
|
||||
|
||||
dirName.append(n);
|
||||
|
||||
std::ofstream myfile(dirName.getPath());
|
||||
std::ofstream myfile(dirName.string());
|
||||
myfile << llvmObjToString(m) << std::endl;
|
||||
}
|
||||
|
||||
@ -327,12 +327,12 @@ void dumpControFlowToJsonFunction(
|
||||
|
||||
void dumpControFlowToJson(
|
||||
llvm::Module* m,
|
||||
utils::FilesystemPath dirName,
|
||||
fs::path dirName,
|
||||
const std::string& fileName)
|
||||
{
|
||||
dirName.append(fileName);
|
||||
|
||||
std::ofstream json(dirName.getPath());
|
||||
std::ofstream json(dirName.string());
|
||||
if (!json.is_open())
|
||||
{
|
||||
return;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "retdec/bin2llvmir/providers/abi/abi.h"
|
||||
#include "retdec/bin2llvmir/utils/llvm.h"
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/patterngen/pattern_extractor/pattern_extractor.h"
|
||||
#include "yaramod/yaramod.h"
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
* Output is set of yara rules (http://yara.readthedocs.io/en/v3.5.0/).
|
||||
*/
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace retdec::patterngen;
|
||||
|
||||
void printUsage(
|
||||
@ -102,7 +101,7 @@ void processArgs(
|
||||
// Read LIST_FILE until EOF
|
||||
while (std::getline(inputObjects, object)) {
|
||||
// Ensure file exists before proceeding
|
||||
if(!FilesystemPath(object).isFile()) {
|
||||
if(!fs::is_regular_file(object)) {
|
||||
printErrorAndDie("argument '" + args[i]
|
||||
+ "' contains the filename '" + object
|
||||
+ "' which is not a valid file");
|
||||
@ -115,7 +114,7 @@ void processArgs(
|
||||
}
|
||||
else {
|
||||
// Input file. Check file on system level.
|
||||
if(!FilesystemPath(args[i]).isFile()) {
|
||||
if(!fs::is_regular_file(args[i])) {
|
||||
printErrorAndDie("argument '" + args[i]
|
||||
+ "' is neither valid file nor argument");
|
||||
return;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "retdec/config/parameters.h"
|
||||
#include "retdec/serdes/address.h"
|
||||
#include "retdec/serdes/std.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -429,17 +429,16 @@ const std::string& Parameters::getBackendVarRenamer() const
|
||||
return _backendVarRenamer;
|
||||
}
|
||||
|
||||
void fixPath(std::string& path, utils::FilesystemPath root)
|
||||
void fixPath(std::string& path, fs::path root)
|
||||
{
|
||||
utils::FilesystemPath p(path);
|
||||
if (p.isRelative())
|
||||
fs::path p(path);
|
||||
if (p.is_relative())
|
||||
{
|
||||
root.append(p.getPath());
|
||||
path = root.getAbsolutePath();
|
||||
path = (root / path).string();
|
||||
}
|
||||
}
|
||||
|
||||
void fixPaths(std::set<std::string>& set, utils::FilesystemPath root)
|
||||
void fixPaths(std::set<std::string>& set, fs::path root)
|
||||
{
|
||||
std::set<std::string> nset;
|
||||
|
||||
@ -454,7 +453,7 @@ void fixPaths(std::set<std::string>& set, utils::FilesystemPath root)
|
||||
|
||||
void Parameters::fixRelativePaths(const std::string& configPath)
|
||||
{
|
||||
utils::FilesystemPath c(configPath);
|
||||
fs::path c(configPath);
|
||||
|
||||
fixPaths(userStaticSignaturePaths, c);
|
||||
fixPaths(staticSignaturePaths, c);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/binary_path.h"
|
||||
#include "retdec/utils/equality.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/cpdetect/cpdetect.h"
|
||||
#include "retdec/cpdetect/heuristics/elf_heuristics.h"
|
||||
@ -217,7 +217,7 @@ CompilerDetector::CompilerDetector(
|
||||
externalSuffixes = EXTERNAL_DATABASE_SUFFIXES;
|
||||
|
||||
bool isFat = false;
|
||||
retdec::utils::FilesystemPath path(pathToShared);
|
||||
fs::path path(pathToShared);
|
||||
path.append(YARA_RULES_PATH);
|
||||
std::set<std::string> formats;
|
||||
std::set<std::string> archs;
|
||||
@ -334,22 +334,22 @@ CompilerDetector::CompilerDetector(
|
||||
*/
|
||||
bool CompilerDetector::getExternalDatabases()
|
||||
{
|
||||
auto thisDir = FilesystemPath(".");
|
||||
auto result = false;
|
||||
|
||||
// iterating over all files in directory
|
||||
for (const auto *subpath : thisDir)
|
||||
for(auto& subpathIt: fs::directory_iterator("."))
|
||||
{
|
||||
if (subpath->isFile()
|
||||
auto subpath = subpathIt.path();
|
||||
if (fs::is_regular_file(subpath)
|
||||
&& std::any_of(externalSuffixes.begin(), externalSuffixes.end(),
|
||||
[&] (const auto &suffix)
|
||||
{
|
||||
return endsWith(subpath->getPath(), suffix);
|
||||
return endsWith(subpath.string(), suffix);
|
||||
}
|
||||
))
|
||||
{
|
||||
result = true;
|
||||
externalDatabase.push_back(subpath->getPath());
|
||||
externalDatabase.push_back(subpath.string());
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,38 +441,41 @@ void CompilerDetector::removeUnusedCompilers()
|
||||
* Expects @p dir structure like this: formats/archs/files
|
||||
*/
|
||||
void CompilerDetector::populateInternalPaths(
|
||||
const retdec::utils::FilesystemPath& dir,
|
||||
const fs::path& dir,
|
||||
const std::set<std::string>& formats,
|
||||
const std::set<std::string>& archs)
|
||||
{
|
||||
if (!dir.isDirectory())
|
||||
if (!fs::is_directory(dir))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto *sub1 : dir)
|
||||
for(auto& sub1It: fs::directory_iterator(dir))
|
||||
{
|
||||
if (!(sub1->isDirectory() && endsWith(sub1->getPath(), formats)))
|
||||
auto sub1 = sub1It.path();
|
||||
if (!(fs::is_directory(sub1) && endsWith(sub1.string(), formats)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto *sub2 : *sub1)
|
||||
for(auto& sub2It: fs::directory_iterator(sub1))
|
||||
{
|
||||
if (!(sub2->isDirectory()
|
||||
&& (archs.empty() || endsWith(sub2->getPath(), archs))))
|
||||
auto sub2 = sub2It.path();
|
||||
if (!(fs::is_directory(sub2)
|
||||
&& (archs.empty() || endsWith(sub2.string(), archs))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto *sub3 : *sub2)
|
||||
for(auto& sub3It: fs::directory_iterator(sub2))
|
||||
{
|
||||
if (!(sub3->isFile() && endsWith(sub3->getPath(), externalSuffixes)))
|
||||
auto sub3 = sub3It.path();
|
||||
if (!(fs::is_regular_file(sub3) && endsWith(sub3.string(), externalSuffixes)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
internalPaths.push_back(sub3->getPath());
|
||||
internalPaths.push_back(sub3.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "retdec/utils/array.h"
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/fileformat/types/symbol_table/elf_symbol.h"
|
||||
#include "retdec/fileformat/utils/other.h"
|
||||
#include "fileinfo/file_detector/elf_detector.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/elf_core_map_plain_getter.h"
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace retdec::fileformat;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/elf_notes_plain_getter.h"
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace retdec::fileformat;
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "retdec/fileformat/utils/conversions.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "fileinfo/file_presentation/getters/simple_getter/visual_basic_plain_getter.h"
|
||||
|
||||
using namespace retdec::utils;
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <regex>
|
||||
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "fileinfo/pattern_detector/pattern_detector.h"
|
||||
#include "retdec/yaracpp/yara_detector.h"
|
||||
@ -311,19 +311,21 @@ void PatternDetector::addFilePaths(const std::string &category, const std::set<s
|
||||
|
||||
for(const auto &item : paths)
|
||||
{
|
||||
FilesystemPath actDir(item);
|
||||
if(actDir.isFile())
|
||||
fs::path actDir(item);
|
||||
if(fs::is_regular_file(actDir))
|
||||
{
|
||||
actCategory->second.insert(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(const auto &file : actDir)
|
||||
if (fs::is_directory(actDir))
|
||||
for(auto& fileIt: fs::directory_iterator(actDir))
|
||||
{
|
||||
const auto path = file->getPath();
|
||||
if(file->isFile() && (endsWith(path, ".yar") || endsWith(path, ".yara")))
|
||||
auto file = fileIt.path();
|
||||
if(fs::is_regular_file(file)
|
||||
&& (endsWith(file.string(), ".yar") || endsWith(file.string(), ".yara")))
|
||||
{
|
||||
actCategory->second.insert(path);
|
||||
actCategory->second.insert(file.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@
|
||||
#include "retdec/llvmir2hll/ir/void_type.h"
|
||||
#include "retdec/llvmir2hll/ir/while_loop_stmt.h"
|
||||
#include "retdec/llvmir2hll/hll/bir_writer.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
|
||||
namespace retdec {
|
||||
namespace llvmir2hll {
|
||||
@ -92,13 +92,13 @@ void BIRWriter::emit(ShPtr<Module> m, const std::string& fileName) {
|
||||
emitGlobals();
|
||||
emitFunctions();
|
||||
|
||||
utils::FilesystemPath dirName(".");
|
||||
fs::path dirName(".");
|
||||
static unsigned cntr = 0;
|
||||
std::string n = fileName.empty()
|
||||
? "dump_" + std::to_string(cntr++) + ".bir"
|
||||
: fileName;
|
||||
dirName.append(n);
|
||||
std::ofstream myfile(dirName.getPath());
|
||||
std::ofstream myfile(dirName.string());
|
||||
myfile << out.str() << std::endl;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "pat2yara/processing.h"
|
||||
#include "yaramod/builder/yara_file_builder.h"
|
||||
#include "yaramod/builder/yara_rule_builder.h"
|
||||
@ -18,7 +18,6 @@
|
||||
* Application for further processing of raw yara rules from bin2pat.
|
||||
*/
|
||||
|
||||
using namespace retdec::utils;
|
||||
using namespace yaramod;
|
||||
|
||||
/**
|
||||
@ -159,7 +158,7 @@ int processArguments(std::vector<std::string> &args)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (FilesystemPath(args[i]).isFile()) {
|
||||
if (fs::is_regular_file(args[i])) {
|
||||
options.input.push_back(args[i]);
|
||||
}
|
||||
else {
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "retdec/macho-extractor/break_fat.h"
|
||||
#include "retdec/unpackertool/unpackertool.h"
|
||||
#include "retdec/utils/binary_path.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/utils/memory.h"
|
||||
|
||||
@ -596,12 +596,11 @@ std::string ProgramOptions::checkFile(
|
||||
const std::string& path,
|
||||
const std::string& errorMsgPrefix)
|
||||
{
|
||||
retdec::utils::FilesystemPath fs(path);
|
||||
if (!fs.exists() || !fs.isFile())
|
||||
if (!fs::is_regular_file(path))
|
||||
{
|
||||
throw std::runtime_error(errorMsgPrefix + " bad file: " + path);
|
||||
}
|
||||
return fs.getAbsolutePath();
|
||||
return fs::absolute(path).string();
|
||||
}
|
||||
|
||||
void ProgramOptions::printHelpAndDie()
|
||||
@ -952,14 +951,14 @@ int main(int argc, char **argv)
|
||||
//
|
||||
retdec::config::Config config;
|
||||
auto binpath = retdec::utils::getThisBinaryDirectoryPath();
|
||||
retdec::utils::FilesystemPath configPath(binpath.getParentPath());
|
||||
fs::path configPath(fs::canonical(binpath).parent_path());
|
||||
configPath.append("share");
|
||||
configPath.append("retdec");
|
||||
configPath.append("decompiler-config.json");
|
||||
if (configPath.exists())
|
||||
if (fs::exists(configPath))
|
||||
{
|
||||
config = retdec::config::Config::fromFile(configPath.getPath());
|
||||
config.parameters.fixRelativePaths(configPath.getParentPath());
|
||||
config = retdec::config::Config::fromFile(configPath.string());
|
||||
config.parameters.fixRelativePaths(fs::canonical(configPath).parent_path().string());
|
||||
}
|
||||
|
||||
// Parse program arguments.
|
||||
|
@ -459,6 +459,7 @@ bool decompile(retdec::config::Config& config, std::string* outString)
|
||||
{
|
||||
if (auto* info = passRegistry.getPassInfo(p))
|
||||
{
|
||||
std::cout << "+++ " << info->getPassName().str() << std::endl;
|
||||
auto* pass = info->createPass();
|
||||
addPass(pm, pass, info);
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "retdec/loader/loader/image.h"
|
||||
#include "retdec/stacofin/stacofin.h"
|
||||
#include "retdec/utils/string.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/yaracpp/yara_detector.h"
|
||||
|
||||
/**
|
||||
@ -77,25 +77,25 @@ void selectSignaturesWithNames(
|
||||
}
|
||||
|
||||
void getAllSignatureFiles(
|
||||
const retdec::utils::FilesystemPath& fp,
|
||||
const fs::path& fp,
|
||||
std::set<std::string>& signFiles,
|
||||
const std::set<std::string>& suffixes = {".yar", ".yara", ".yarac"})
|
||||
{
|
||||
if (fp.isFile()
|
||||
if (fs::is_regular_file(fp)
|
||||
&& std::any_of(suffixes.begin(), suffixes.end(),
|
||||
[&] (const auto &suffix)
|
||||
{
|
||||
return endsWith(fp.getPath(), suffix);
|
||||
return endsWith(fp.string(), suffix);
|
||||
}
|
||||
))
|
||||
{
|
||||
signFiles.insert(fp.getAbsolutePath());
|
||||
signFiles.insert(fs::absolute(fp).string());
|
||||
}
|
||||
else if (fp.isDirectory())
|
||||
else if (fs::is_directory(fp))
|
||||
{
|
||||
for (auto* s : fp)
|
||||
for (auto& s : fs::directory_iterator(fp))
|
||||
{
|
||||
getAllSignatureFiles(*s, signFiles);
|
||||
getAllSignatureFiles(s, signFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -109,7 +109,7 @@ std::set<std::string> selectSignaturePaths(
|
||||
std::set<std::string> sigs;
|
||||
for (auto& p : c.parameters.userStaticSignaturePaths)
|
||||
{
|
||||
getAllSignatureFiles(utils::FilesystemPath(p), sigs);
|
||||
getAllSignatureFiles(fs::path(p), sigs);
|
||||
}
|
||||
|
||||
// Select only specific signatures from retdec's database.
|
||||
@ -117,7 +117,7 @@ std::set<std::string> selectSignaturePaths(
|
||||
std::set<std::string> allSigs;
|
||||
for (auto& p : c.parameters.staticSignaturePaths)
|
||||
{
|
||||
getAllSignatureFiles(utils::FilesystemPath(p), allSigs);
|
||||
getAllSignatureFiles(fs::path(p), allSigs);
|
||||
}
|
||||
|
||||
std::string archSize = std::to_string(image.getWordLength());
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/stacofin/stacofin.h"
|
||||
#include "retdec/loader/image_factory.h"
|
||||
|
||||
@ -135,12 +135,12 @@ int doActions(
|
||||
}
|
||||
else if (args[i] == "-b" && i + 1 < args.size()) {
|
||||
binaryPath = args[++i];
|
||||
if (!FilesystemPath(binaryPath).isFile()) {
|
||||
if (!fs::is_regular_file(binaryPath)) {
|
||||
return printError("invalid binary file '" + binaryPath + "'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!FilesystemPath(args[i]).isFile()) {
|
||||
if (!fs::is_regular_file(args[i])) {
|
||||
return printError("invalid yara file '" + args[i] + "'");
|
||||
}
|
||||
yaraPaths.push_back(args[i]);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "retdec/utils/conversion.h"
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/filesystem.h"
|
||||
#include "retdec/utils/memory.h"
|
||||
#include "retdec/cpdetect/cpdetect.h"
|
||||
#include "retdec/fileformat/fileformat.h"
|
||||
|
@ -7,7 +7,6 @@ add_library(utils STATIC
|
||||
crc32.cpp
|
||||
dynamic_buffer.cpp
|
||||
file_io.cpp
|
||||
filesystem_path.cpp
|
||||
math.cpp
|
||||
memory.cpp
|
||||
string.cpp
|
||||
@ -29,6 +28,18 @@ target_link_libraries(utils
|
||||
retdec::deps::whereami
|
||||
)
|
||||
|
||||
# We may need to link filesystem library manually.
|
||||
find_library(STD_CPP_FS stdc++fs)
|
||||
if (STD_CPP_FS)
|
||||
message("-- Linking with ${STD_CPP_FS} library")
|
||||
target_link_libraries(utils
|
||||
PRIVATE
|
||||
stdc++fs
|
||||
)
|
||||
else()
|
||||
message("-- Library stdc++fs NOT FOUND -> linking utils without stdc++fs library")
|
||||
endif()
|
||||
|
||||
# Disable the min() and max() macros to prevent errors when using e.g.
|
||||
# std::numeric_limits<...>::max()
|
||||
# (http://stackoverflow.com/questions/1904635/warning-c4003-and-errors-c2589-and-c2059-on-x-stdnumeric-limitsintmax).
|
||||
|
@ -47,12 +47,12 @@ namespace utils {
|
||||
*
|
||||
* @return absolute path
|
||||
*/
|
||||
FilesystemPath getThisBinaryPath()
|
||||
fs::path getThisBinaryPath()
|
||||
{
|
||||
std::size_t dirPathSize = 0;
|
||||
std::string path = getStringThisBinaryPath(dirPathSize);
|
||||
|
||||
return FilesystemPath(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ FilesystemPath getThisBinaryPath()
|
||||
*
|
||||
* @return absolute path
|
||||
*/
|
||||
FilesystemPath getThisBinaryDirectoryPath()
|
||||
fs::path getThisBinaryDirectoryPath()
|
||||
{
|
||||
std::size_t dirPathSize = 0;
|
||||
std::string path = getStringThisBinaryPath(dirPathSize);
|
||||
@ -70,7 +70,7 @@ FilesystemPath getThisBinaryDirectoryPath()
|
||||
path.erase(dirPathSize + 1);
|
||||
}
|
||||
|
||||
return FilesystemPath(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
@ -1,430 +0,0 @@
|
||||
/**
|
||||
* @file src/utils/filesystem_path.cpp
|
||||
* @brief FilesystemPath class implementation for unified work with filepaths.
|
||||
* @copyright (c) 2017 Avast Software, licensed under the MIT license
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
#include "retdec/utils/filesystem_path.h"
|
||||
#include "retdec/utils/os.h"
|
||||
#include "retdec/utils/scope_exit.h"
|
||||
#include "retdec/utils/string.h"
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
#include <filesystem>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
namespace retdec {
|
||||
namespace utils {
|
||||
|
||||
class FilesystemPathImpl
|
||||
{
|
||||
public:
|
||||
FilesystemPathImpl(const std::string& path) : _path()
|
||||
{
|
||||
changePath(path);
|
||||
}
|
||||
|
||||
FilesystemPathImpl(const FilesystemPathImpl& rhs) : _path(rhs._path) {}
|
||||
virtual ~FilesystemPathImpl() = default;
|
||||
|
||||
/**
|
||||
* Returns the path.
|
||||
*
|
||||
* @return Path.
|
||||
*/
|
||||
const std::string& getPath() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the path to the new path. All '/' in the path are replaced
|
||||
* with the system specific path separator. Separator present at the end
|
||||
* of the path (in case of directories) is removed.
|
||||
*
|
||||
* @param path Path to change.
|
||||
*/
|
||||
void changePath(std::string path)
|
||||
{
|
||||
std::replace(path.begin(), path.end(), '/', pathSeparator);
|
||||
_path = endsWith(path, pathSeparator) ? path.substr(0, path.length() - 1) : path;
|
||||
}
|
||||
|
||||
virtual std::string getAbsolutePath() = 0;
|
||||
virtual std::string getParentPath() = 0;
|
||||
virtual bool subpathsInDirectory(std::vector<std::string>& subpaths) = 0;
|
||||
virtual bool exists() = 0;
|
||||
virtual bool isFile() = 0;
|
||||
virtual bool isDirectory() = 0;
|
||||
virtual bool isAbsolute() = 0;
|
||||
|
||||
static char pathSeparator;
|
||||
|
||||
protected:
|
||||
std::string _path;
|
||||
};
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
char FilesystemPathImpl::pathSeparator = '\\';
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class FilesystemPathImplWindows : public FilesystemPathImpl
|
||||
{
|
||||
public:
|
||||
FilesystemPathImplWindows(const std::string& path) : FilesystemPathImpl(path) {}
|
||||
FilesystemPathImplWindows(const FilesystemPathImplWindows& rhs): FilesystemPathImpl(rhs) {}
|
||||
|
||||
virtual std::string getAbsolutePath() override
|
||||
{
|
||||
return fs::absolute(_path).string();
|
||||
}
|
||||
|
||||
virtual std::string getParentPath() override
|
||||
{
|
||||
return fs::path(_path).parent_path().string();
|
||||
}
|
||||
|
||||
virtual bool subpathsInDirectory(std::vector<std::string>& subpaths) override
|
||||
{
|
||||
subpaths.clear();
|
||||
|
||||
if (!isDirectory())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special paths '.' and '..' are skipped.
|
||||
for(auto& p: std::filesystem::directory_iterator(_path))
|
||||
{
|
||||
subpaths.emplace_back(p.path().string());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool exists() override
|
||||
{
|
||||
return std::filesystem::exists(_path);
|
||||
}
|
||||
|
||||
virtual bool isFile() override
|
||||
{
|
||||
return std::filesystem::is_regular_file(_path);
|
||||
}
|
||||
|
||||
virtual bool isDirectory() override
|
||||
{
|
||||
return std::filesystem::is_directory(_path);
|
||||
}
|
||||
|
||||
virtual bool isAbsolute() override
|
||||
{
|
||||
return fs::path(_path).is_absolute();
|
||||
}
|
||||
};
|
||||
#else
|
||||
char FilesystemPathImpl::pathSeparator = '/';
|
||||
|
||||
class FilesystemPathImplUnix : public FilesystemPathImpl
|
||||
{
|
||||
public:
|
||||
FilesystemPathImplUnix(const std::string& path) : FilesystemPathImpl(path) {}
|
||||
FilesystemPathImplUnix(const FilesystemPathImplUnix& rhs) : FilesystemPathImpl(rhs) {}
|
||||
|
||||
virtual std::string getAbsolutePath() override
|
||||
{
|
||||
#ifdef PATH_MAX
|
||||
char absolutePath[PATH_MAX] = { '\0' };
|
||||
if (realpath(_path.c_str(), absolutePath) == nullptr)
|
||||
return {};
|
||||
#else
|
||||
char* absolutePathStr = realpath(_path.c_str(), nullptr);
|
||||
SCOPE_EXIT {
|
||||
free(absolutePathStr);
|
||||
};
|
||||
std::string absolutePath = absolutePathStr;
|
||||
#endif
|
||||
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
virtual std::string getParentPath() override
|
||||
{
|
||||
// dirname() can modify the path provided in parameter, so we need to make copy
|
||||
char* copyPathStr = new char[_path.length() + 1];
|
||||
SCOPE_EXIT {
|
||||
delete[] copyPathStr;
|
||||
};
|
||||
strcpy(copyPathStr, _path.c_str());
|
||||
|
||||
// get the parent directory by calling dirname()
|
||||
return dirname(copyPathStr);
|
||||
}
|
||||
|
||||
virtual bool subpathsInDirectory(std::vector<std::string>& subpaths) override
|
||||
{
|
||||
subpaths.clear();
|
||||
DIR* dir = opendir(_path.c_str());
|
||||
if (dir == nullptr)
|
||||
return false;
|
||||
|
||||
dirent* node;
|
||||
while ((node = readdir(dir)) != nullptr)
|
||||
{
|
||||
// skip these 2 special links
|
||||
// "." is just link to the current directory
|
||||
// ".." is link to the parent directory
|
||||
if (strcmp(node->d_name, ".") == 0 || strcmp(node->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
std::string newPath(_path);
|
||||
newPath += pathSeparator;
|
||||
newPath.append(node->d_name);
|
||||
subpaths.emplace_back(newPath);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool exists() override
|
||||
{
|
||||
struct stat st;
|
||||
return stat(_path.c_str(), &st) == 0;
|
||||
}
|
||||
|
||||
virtual bool isFile() override
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(_path.c_str(), &st) != 0)
|
||||
return false;
|
||||
|
||||
return S_ISREG(st.st_mode);
|
||||
}
|
||||
|
||||
virtual bool isDirectory() override
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(_path.c_str(), &st) != 0)
|
||||
return false;
|
||||
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
virtual bool isAbsolute() override
|
||||
{
|
||||
return startsWith(_path, pathSeparator);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param path The path of the node in the filesystem.
|
||||
*/
|
||||
FilesystemPath::FilesystemPath(const std::string& path) : _impl(nullptr), _subpathsLoaded(false), _subpaths()
|
||||
{
|
||||
#ifdef OS_WINDOWS
|
||||
_impl = std::make_unique<FilesystemPathImplWindows>(path);
|
||||
#else
|
||||
_impl = std::make_unique<FilesystemPathImplUnix>(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*
|
||||
* @param fspath FilesystemPath object to copy.
|
||||
*/
|
||||
FilesystemPath::FilesystemPath(const FilesystemPath& fspath) : FilesystemPath(fspath.getPath())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
FilesystemPath::~FilesystemPath() = default;
|
||||
|
||||
/**
|
||||
* Returns the path in the normalized textual representation
|
||||
* (which always contains separator at end of path).
|
||||
*
|
||||
* @return The path of the node in normalized representation.
|
||||
*/
|
||||
std::string FilesystemPath::getPath() const
|
||||
{
|
||||
return _impl->getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the parent directory of this path in textual representation.
|
||||
*
|
||||
* @return Parent path.
|
||||
*/
|
||||
std::string FilesystemPath::getParentPath() const
|
||||
{
|
||||
return _impl->getParentPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute path.
|
||||
*
|
||||
* @return Absolute path.
|
||||
*/
|
||||
std::string FilesystemPath::getAbsolutePath() const
|
||||
{
|
||||
return _impl->getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the @ref iterator pointing to the first subpath. Performs lazy loading.
|
||||
*
|
||||
* @return The pointer to the first subpath.
|
||||
*/
|
||||
FilesystemPath::iterator FilesystemPath::begin()
|
||||
{
|
||||
if (!_subpathsLoaded)
|
||||
loadSubpaths();
|
||||
|
||||
return iterator(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the @ref iterator pointing to the last subpath. Performs lazy loading.
|
||||
*
|
||||
* @return The pointer to the last subpath.
|
||||
*/
|
||||
FilesystemPath::iterator FilesystemPath::end()
|
||||
{
|
||||
if (!_subpathsLoaded)
|
||||
loadSubpaths();
|
||||
|
||||
return iterator(this, _subpaths.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the @ref iterator pointing to the first subpath. Performs lazy loading.
|
||||
*
|
||||
* @return The pointer to the first subpath.
|
||||
*/
|
||||
FilesystemPath::const_iterator FilesystemPath::begin() const
|
||||
{
|
||||
if (!_subpathsLoaded)
|
||||
loadSubpaths();
|
||||
|
||||
return const_iterator(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the @ref iterator pointing to the last subpath. Performs lazy loading.
|
||||
*
|
||||
* @return The pointer to the last subpath.
|
||||
*/
|
||||
FilesystemPath::const_iterator FilesystemPath::end() const
|
||||
{
|
||||
if (!_subpathsLoaded)
|
||||
loadSubpaths();
|
||||
|
||||
return const_iterator(this, _subpaths.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the path refers to an existing file or directory.
|
||||
*
|
||||
* @return @c true if exists, otherwise @c false.
|
||||
*/
|
||||
bool FilesystemPath::exists() const
|
||||
{
|
||||
return _impl->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the path is directory or not. The path doesn't have to be loaded.
|
||||
*
|
||||
* @return True if the path is directory, otherwise false.
|
||||
*/
|
||||
bool FilesystemPath::isDirectory() const
|
||||
{
|
||||
return _impl->isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the path is file or not. The path doesn't have to be loaded.
|
||||
*
|
||||
* @return True if the path is file, otherwise false.
|
||||
*/
|
||||
bool FilesystemPath::isFile() const
|
||||
{
|
||||
return _impl->isFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the path is absolute or not. The path doesn't have to be loaded.
|
||||
*
|
||||
* @return True if the path is absolute, otherwise false.
|
||||
*/
|
||||
bool FilesystemPath::isAbsolute() const
|
||||
{
|
||||
return _impl->isAbsolute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the path is relative or not. The path doesn't have to be loaded.
|
||||
*
|
||||
* @return True if the path is relative, otherwise false.
|
||||
*/
|
||||
bool FilesystemPath::isRelative() const
|
||||
{
|
||||
return !_impl->isAbsolute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the path to the current path with correct separator.
|
||||
*
|
||||
* @param path Path to append.
|
||||
*/
|
||||
void FilesystemPath::append(const std::string& path)
|
||||
{
|
||||
_impl->changePath(getPath() + separator() + path);
|
||||
_subpathsLoaded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path component separator used on the specific system.
|
||||
*
|
||||
* @return Path separator.
|
||||
*/
|
||||
char FilesystemPath::separator()
|
||||
{
|
||||
return FilesystemPathImpl::pathSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the subpaths in the path represented by object.
|
||||
*/
|
||||
void FilesystemPath::loadSubpaths() const
|
||||
{
|
||||
_subpaths.clear();
|
||||
|
||||
std::vector<std::string> subpaths;
|
||||
if (!_impl->subpathsInDirectory(subpaths))
|
||||
return;
|
||||
|
||||
std::transform(subpaths.begin(), subpaths.end(), std::back_inserter(_subpaths),
|
||||
[](const auto& subpath) {
|
||||
return std::make_unique<FilesystemPath>(subpath);
|
||||
});
|
||||
|
||||
_subpathsLoaded = true;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace retdec
|
@ -25,8 +25,8 @@ class ThisBinaryPathTests: public Test {};
|
||||
|
||||
TEST_F(ThisBinaryPathTests,
|
||||
CorrectBinaryPathDetection) {
|
||||
EXPECT_TRUE(getThisBinaryPath().exists());
|
||||
EXPECT_TRUE(getThisBinaryPath().isFile());
|
||||
EXPECT_TRUE(fs::exists(getThisBinaryPath()));
|
||||
EXPECT_TRUE(fs::is_regular_file(getThisBinaryPath()));
|
||||
}
|
||||
|
||||
//
|
||||
@ -35,8 +35,8 @@ CorrectBinaryPathDetection) {
|
||||
|
||||
TEST_F(ThisBinaryPathTests,
|
||||
CorrectBinaryDirPathDetection) {
|
||||
EXPECT_TRUE(getThisBinaryDirectoryPath().exists());
|
||||
EXPECT_TRUE(getThisBinaryDirectoryPath().isDirectory());
|
||||
EXPECT_TRUE(fs::exists(getThisBinaryDirectoryPath()));
|
||||
EXPECT_TRUE(fs::is_directory(getThisBinaryDirectoryPath()));
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
|
Loading…
Reference in New Issue
Block a user