diff --git a/include/exiv2/futils.hpp b/include/exiv2/futils.hpp index 9ad7a83b..4d0ea6d5 100644 --- a/include/exiv2/futils.hpp +++ b/include/exiv2/futils.hpp @@ -175,6 +175,9 @@ namespace Exiv2 */ EXIV2API std::string strError(); + //! @brief Return the path of the current process. + EXIV2API std::string getProcessPath(); + /*! @brief A container for URL components. It also provides the method to parse a URL to get the protocol, host, path, port, querystring, username, password. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 879b194a..8ab35c53 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -217,7 +217,8 @@ set_target_properties( exiv2lib_int PROPERTIES target_compile_definitions(exiv2lib PUBLIC - EXV_LOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}" + EXV_LOCALEDIR="../${CMAKE_INSTALL_LOCALEDIR}" + #EXV_LOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}" ) if ( UNIX AND CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) diff --git a/src/futils.cpp b/src/futils.cpp index 7b862d4f..4debd3a9 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -33,13 +33,20 @@ // + standard includes #include #include + #ifdef _MSC_VER -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) + # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) + #include // For access to GetModuleFileNameEx +#elif defined(__APPLE__) + #include #endif + #ifdef EXV_HAVE_UNISTD_H -# include // for stat() + # include // for stat() #endif + + #include #include #include @@ -451,5 +458,43 @@ namespace Exiv2 { result.QueryString = std::string(queryStart, uri.end()); return result; - } // Uri::Parse + } + + std::string getProcessPath() + { + std::string ret("unknown"); + #if defined(WIN32) + HANDLE processHandle = NULL; + processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId()); + if (processHandle != NULL) { + TCHAR filename[MAX_PATH]; + if (GetModuleFileNameEx(processHandle, NULL, filename, MAX_PATH) != 0) { + ret = filename; + } + CloseHandle(processHandle); + } + #elif defined(__APPLE__) + const int pid = getpid(); + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + if (proc_pidpath (pid, pathbuf, sizeof(pathbuf)) > 0) { + ret = pathbuf; + } + #elif defined(__linux__) + // http://stackoverflow.com/questions/606041/how-do-i-get-the-path-of-a-process-in-unix-linux + char proc[100]; + char path[500]; + sprintf(proc,"/proc/%d/exe", getpid()); + ssize_t l = readlink (proc, path,sizeof(path)-1); + if (l>0) { + path[l]=0; + ret = path; + } + #endif + #if defined(WIN32) + const size_t idxLastSeparator = ret.find_last_of('\\'); + #else + const size_t idxLastSeparator = ret.find_last_of('/'); + #endif + return ret.substr(0, idxLastSeparator); + } } // namespace Exiv2 diff --git a/unitTests/test_futils.cpp b/unitTests/test_futils.cpp index 47e6c481..950b2d73 100644 --- a/unitTests/test_futils.cpp +++ b/unitTests/test_futils.cpp @@ -153,3 +153,17 @@ TEST(AUri, parsesAndDecoreUrl) Uri::Decode(uri); } + +TEST(getProcessPath, obtainPathOfUnitTestsExecutable) +{ +#ifdef _WIN32 + const std::string expectedName("bin"); +#else + const std::string expectedName("bin"); +#endif + const std::string path = getProcessPath(); + + ASSERT_FALSE(path.empty()); + const size_t idxStart = path.size() - expectedName.size(); + ASSERT_EQ(expectedName, path.substr(idxStart, expectedName.size())); +}