From 9432d12c2bf55effa2f46b1fdde8bdb6759eba9a Mon Sep 17 00:00:00 2001 From: Andrey Astafyev Date: Sat, 19 Oct 2019 06:38:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D1=91=D0=BD=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20whereami?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 3 - CMakeLists.txt | 7 - examples/filesystem/01_minimal/CMakeLists.txt | 1 - src/filesystem/CMakeLists.txt | 4 +- src/filesystem/whereami.cpp | 311 ++++++++++++++++++ src/filesystem/whereami.hpp | 121 +++++++ thirdparty/whereami | 1 - 7 files changed, 434 insertions(+), 14 deletions(-) create mode 100644 src/filesystem/whereami.cpp create mode 100644 src/filesystem/whereami.hpp delete mode 160000 thirdparty/whereami diff --git a/.gitmodules b/.gitmodules index 9d64d59..6c3ddd7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,3 @@ [submodule "cmake/generators"] path = cmake/generators url = ../../f1x1t/cmake-generators -[submodule "thirdparty/whereami"] - path = thirdparty/whereami - url = ../../f1x1t/whereami.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c4c2ca7..0d18bb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,13 +52,6 @@ if (BUILD_EXAMPLES) add_subdirectory(examples/log) endif() -ExternalProject_Add(whereami - SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/whereami - INSTALL_DIR ${CMAKE_BINARY_DIR} - DOWNLOAD_COMMAND "" - CONFIGURE_COMMAND ${CMAKE_COMMAND} -"G${CMAKE_GENERATOR}" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} -DBUILD_SHARED_LIBS=OFF -DBUILD_EXAMPLES=OFF - ) - add_breathe_target( TARGET_NAME doc-breathe SOURCE_DIR ${CMAKE_SOURCE_DIR}/doc/html diff --git a/examples/filesystem/01_minimal/CMakeLists.txt b/examples/filesystem/01_minimal/CMakeLists.txt index 896dbfe..6108d29 100644 --- a/examples/filesystem/01_minimal/CMakeLists.txt +++ b/examples/filesystem/01_minimal/CMakeLists.txt @@ -21,7 +21,6 @@ add_pvs_check(${current_target}) add_dependencies(${current_target} base) add_dependencies(${current_target} filesystem) -add_dependencies(${current_target} whereami) # Qt5 # qt_translation(TARGET ${current_target} TS_DIR ${CMAKE_SOURCE_DIR}/l10n LANGUAGES ru_RU) diff --git a/src/filesystem/CMakeLists.txt b/src/filesystem/CMakeLists.txt index 508709d..f5f1dc4 100644 --- a/src/filesystem/CMakeLists.txt +++ b/src/filesystem/CMakeLists.txt @@ -4,19 +4,19 @@ set(current_target filesystem) # Список файлов исходных текстов set(current_target_sources ${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/whereami.cpp ) # Список заголовочных файлов (используется для установки) set(current_target_headers ${CMAKE_CURRENT_SOURCE_DIR}/paths.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/whereami.hpp ) add_common_library(TARGET ${current_target} OUTPUT_NAME myx-${current_target} SOURCES ${current_target_sources}) common_target_properties(${current_target}) -add_dependencies(${current_target} whereami) - add_clang_tidy_check(${current_target} ${current_target_sources}) add_clang_analyze_check(${current_target} ${current_target_sources}) diff --git a/src/filesystem/whereami.cpp b/src/filesystem/whereami.cpp new file mode 100644 index 0000000..5145ae2 --- /dev/null +++ b/src/filesystem/whereami.cpp @@ -0,0 +1,311 @@ +#if !defined( WHEREAMIPP_H ) +#include +#endif + +namespace whereami { + +namespace { + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef WAI_NOINLINE +#if defined( _MSC_VER ) +#define WAI_NOINLINE __declspec( noinline ) +#elif defined( __GNUC__ ) +#define WAI_NOINLINE __attribute__( ( noinline ) ) +#else +#error unsupported compiler +#endif +#endif + +#if defined( _MSC_VER ) +#define WAI_RETURN_ADDRESS() _ReturnAddress() +#elif defined( __GNUC__ ) +#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr( __builtin_return_address( 0 ) ) +#else +#error unsupported compiler +#endif + + +#include +#include +#include +#if defined( __linux__ ) +#include +#else +#include +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include + +#if !defined( WAI_PROC_SELF_EXE ) +#define WAI_PROC_SELF_EXE "/proc/self/exe" +#endif + + +int getExecutablePath( char* out, int capacity, int* dirname_length ) +{ + char buffer[PATH_MAX]; + char* resolved = nullptr; + int length = -1; + + for (;; ) + { + resolved = realpath( WAI_PROC_SELF_EXE, buffer ); + if ( !resolved ) + { + break; + } + + length = static_cast< int >( strlen( resolved ) ); + if ( length <= capacity ) + { + memcpy( out, resolved, static_cast< size_t >( length ) ); + + if ( dirname_length ) + { + int i; + + for ( i = length - 1; i >= 0; --i ) + { + if ( out[i] == '/' ) + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + + return( length ); +} // getExecutablePath + + +#if !defined( WAI_PROC_SELF_MAPS_RETRY ) +#define WAI_PROC_SELF_MAPS_RETRY 5 +#endif + +#if !defined( WAI_PROC_SELF_MAPS ) +#if defined( __sun ) +#define WAI_PROC_SELF_MAPS "/proc/self/map" +#else +#define WAI_PROC_SELF_MAPS "/proc/self/maps" +#endif +#endif + +#if defined( __ANDROID__ ) || defined( ANDROID ) +#include +#include +#include +#endif + + +WAI_NOINLINE +int getModulePath( char* out, int capacity, int* dirname_length ) +{ + int length = -1; + FILE* maps = nullptr; + + for ( int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r ) + { + maps = fopen( WAI_PROC_SELF_MAPS, "r" ); + if ( !maps ) + { + break; + } + + for (;; ) + { + char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX]; + uint64_t low, high; + char perms[5]; + uint64_t offset; + uint32_t major, minor; + char path[PATH_MAX]; + uint32_t inode; + + if ( !fgets( buffer, sizeof( buffer ), maps ) ) + { + break; + } + + if ( sscanf( buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path ) == 8 ) + { + uint64_t addr = reinterpret_cast< uintptr_t >( WAI_RETURN_ADDRESS() ); + if ( ( low <= addr ) && ( addr <= high ) ) + { + char* resolved; + + resolved = realpath( path, buffer ); + if ( !resolved ) + { + break; + } + + length = static_cast< int >( strlen( resolved ) ); + if ( length <= capacity ) + { + memcpy( out, resolved, static_cast< size_t >( length ) ); + + if ( dirname_length ) + { + int i; + + for ( i = length - 1; i >= 0; --i ) + { + if ( out[i] == '/' ) + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + } + } + + fclose( maps ); + maps = nullptr; + + if ( length != -1 ) + { + break; + } + } + + if ( maps ) + { + fclose( maps ); + } + + return( length ); +} // getModulePath + + +#ifdef __cplusplus + +} // namespace +#endif + +} // namespace + + +whereami_string_t whereami_path_t::dirname() const +{ + return( m_path.substr( 0, static_cast< size_t >( m_dirnameLength ) ) ); +} + + +whereami_string_t whereami_path_t::basename() const +{ + return( m_path.substr( static_cast< size_t >( m_dirnameLength + 1 ) ) ); +} + + +#if defined( WHEREAMI_CXX11 ) +whereami_path_t::operator whereami_string_t() && +{ + return( std::move( m_path ) ); +} + +whereami_path_t::operator whereami_string_t() const & +{ + return( m_path ); +} + + +#else +whereami_path_t::operator const whereami_string_t&() const +{ + return( m_path ); +} + + +#endif // if defined( WHEREAMI_CXX11 ) + +#if defined( WHEREAMI_CXX11 ) +whereami_path_t::whereami_path_t( whereami_string_t&& path, int dirname_length ) noexcept + : m_path( std::move( path ) ), + m_dirnameLength( dirname_length ) +{ +} + + +#else +whereami_path_t::whereami_path_t( whereami_string_t& path, int dirname_length ) + : m_path( path ), + m_dirnameLength( dirname_length ) +{ +} + + +#endif + +#if !defined( WHEREAMI_DISABLE_OSTREAM ) +std::ostream& operator<<( std::ostream& os, const whereami_path_t& path ) +{ + return( os << path.m_path ); +} + + +#endif + + +whereami_path_t getExecutablePath() +{ + whereami_string_t path; + int dirname_length = -1; + + int length = getExecutablePath( nullptr, 0, nullptr ); + + if ( length != -1 ) + { + path.resize( static_cast< size_t >( length ) ); + getExecutablePath( &path[0], length, &dirname_length ); + } + + #if defined( WHEREAMI_CXX11 ) + return( whereami_path_t( std::move( path ), dirname_length ) ); + + #else + return( whereami_path_t( path, dirname_length ) ); + + #endif +} + + +whereami_path_t getModulePath() +{ + whereami_string_t path; + int dirname_length = -1; + + int length = getModulePath( nullptr, 0, nullptr ); + + if ( length != -1 ) + { + path.resize( static_cast< size_t >( length ) ); + getModulePath( &path[0], length, &dirname_length ); + } + + #if defined( WHEREAMI_CXX11 ) + return( whereami_path_t( std::move( path ), dirname_length ) ); + + #else + return( whereami_path_t( path, dirname_length ) ); + + #endif +} + +} // namespace whereami diff --git a/src/filesystem/whereami.hpp b/src/filesystem/whereami.hpp new file mode 100644 index 0000000..3237a2a --- /dev/null +++ b/src/filesystem/whereami.hpp @@ -0,0 +1,121 @@ +#ifndef WHEREAMIPP_HPP_ +#define WHEREAMIPP_HPP_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Returns the path to the current executable. + * + * Usage: + * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to + * retrieve the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the + * path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the executable path on success (without a terminal NUL + * character), otherwise `-1` + */ +int getExecutablePath( char* out, int capacity, int* dirname_length ); + +/** + * Returns the path to the current module. + * + * Usage: + * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve + * the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the module path on success (without a terminal NUL + * character), otherwise `-1` + */ + +int getModulePath( char* out, int capacity, int* dirname_length ); + +#ifdef __cplusplus +} +#endif + + +#if !defined( WHEREAMI_STRING_T ) +#include +typedef std::string whereami_string_t; +#else +typedef WHEREAMI_STRING_T whereami_string_t; +#endif +#if !defined( WHEREAMI_DISABLE_OSTREAM ) +#include +#endif + +#if ( defined ( __cplusplus ) && ( __cplusplus > 199711L ) ) || ( defined( _MSC_FULL_VER ) && ( _MSC_FULL_VER >= 150020706 ) ) + #define WHEREAMI_CXX11 +#endif + +#if defined( __GNUC__ ) +#if !( ( __GNUC__ * 100 + __GNUC_MINOR__ ) < 408 ) + #undef WHEREAMI_CXX11 +#endif +#endif + + +namespace whereami { + +class whereami_path_t +{ +public: + #if defined( WHEREAMI_CXX11 ) + operator whereami_string_t() &&; + operator whereami_string_t() const &; + #else + operator const whereami_string_t&() const; + #endif + whereami_string_t dirname() const; + whereami_string_t basename() const; + +private: + whereami_path_t(); + + #if defined( WHEREAMI_CXX11 ) + whereami_path_t( whereami_string_t&& path, int dirname_length ) noexcept; + #else + whereami_path_t( whereami_string_t& m_path, int m_dirnameLength ); + #endif + + friend whereami_path_t getExecutablePath(); + friend whereami_path_t getModulePath(); + #if !defined( WHEREAMI_DISABLE_OSTREAM ) + friend std::ostream& operator<<( std::ostream& os, const whereami_path_t& m_path ); + #endif + + whereami_string_t m_path; + int m_dirnameLength; +}; // class whereami_path_t + +/** + * Returns the path to the current executable. + */ +whereami_path_t getExecutablePath(); + +/** + * Returns the path to the current module. + */ +whereami_path_t getModulePath(); + +} // namespace whereami + +#endif // #ifndef WHEREAMIPP_H diff --git a/thirdparty/whereami b/thirdparty/whereami deleted file mode 160000 index 6706e7e..0000000 --- a/thirdparty/whereami +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6706e7e4c5bad07e2ea5abed6feb032bb1cef652