diff --git a/Foundation/include/Poco/Path.h b/Foundation/include/Poco/Path.h index 0f0a889d0b..cf6b76abd5 100644 --- a/Foundation/include/Poco/Path.h +++ b/Foundation/include/Poco/Path.h @@ -290,6 +290,10 @@ class Foundation_API Path /// this is the semicolon ';'. On OpenVMS systems, this is the /// comma ','. + static std::string self(); + /// Return path to the executable file, empty string if failed. + /// The path is absolute one. + static std::string current(); /// Returns the current working directory. diff --git a/Foundation/include/Poco/Path_UNIX.h b/Foundation/include/Poco/Path_UNIX.h index 50a6478b92..8e27bd9622 100644 --- a/Foundation/include/Poco/Path_UNIX.h +++ b/Foundation/include/Poco/Path_UNIX.h @@ -28,6 +28,7 @@ namespace Poco { class PathImpl { public: + static std::string selfImpl(); static std::string currentImpl(); static std::string homeImpl(); static std::string configHomeImpl(); @@ -39,6 +40,7 @@ class PathImpl static std::string nullImpl(); static std::string expandImpl(const std::string& path); static void listRootsImpl(std::vector& roots); + }; diff --git a/Foundation/include/Poco/Path_WIN32U.h b/Foundation/include/Poco/Path_WIN32U.h index fb9d451cc2..c72d78ef50 100644 --- a/Foundation/include/Poco/Path_WIN32U.h +++ b/Foundation/include/Poco/Path_WIN32U.h @@ -28,6 +28,7 @@ namespace Poco { class Foundation_API PathImpl { public: + static std::string selfImpl(); static std::string currentImpl(); static std::string homeImpl(); static std::string configHomeImpl(); diff --git a/Foundation/include/Poco/Path_WINCE.h b/Foundation/include/Poco/Path_WINCE.h index 37e3fff582..32677150d4 100644 --- a/Foundation/include/Poco/Path_WINCE.h +++ b/Foundation/include/Poco/Path_WINCE.h @@ -28,6 +28,7 @@ namespace Poco { class Foundation_API PathImpl { public: + static std::string selfImpl(); static std::string currentImpl(); static std::string homeImpl(); static std::string configHomeImpl(); diff --git a/Foundation/src/Path.cpp b/Foundation/src/Path.cpp index 38d354eb4d..23e83aeb8f 100644 --- a/Foundation/src/Path.cpp +++ b/Foundation/src/Path.cpp @@ -578,6 +578,12 @@ Path& Path::clear() } +std::string Path::self() +{ + return PathImpl::selfImpl(); +} + + std::string Path::current() { return PathImpl::currentImpl(); diff --git a/Foundation/src/Path_UNIX.cpp b/Foundation/src/Path_UNIX.cpp index 697e0f6410..1856728e55 100644 --- a/Foundation/src/Path_UNIX.cpp +++ b/Foundation/src/Path_UNIX.cpp @@ -19,19 +19,74 @@ #include #include #include +#include + #if !defined(POCO_VXWORKS) #include #endif -#include + +#if POCO_OS == POCO_OS_MAC_OS_X +#include +#elif POCO_OS == POCO_OS_FREE_BSD +#include +#elif POCO_OS == POCO_OS_LINUX +#include +#endif #ifndef PATH_MAX -#define PATH_MAX 1024 // fallback +#define PATH_MAX 4096 // fallback #endif - namespace Poco { +std::string PathImpl::selfImpl() +{ + std::string path; + char buf[PATH_MAX + 1] {0}; + +#if POCO_OS == POCO_OS_MAC_OS_X + std::uint32_t size = sizeof(buf); + if (_NSGetExecutablePath(buf, &size) == 0) + path = buf; + else + throw Poco::SystemException("Cannot get path of the current process."); +#elif POCO_OS == POCO_OS_FREE_BSD + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + std::size_t size = sizeof(buf); + if (sysctl(mib, 4, buf, &size, NULL, 0) == 0) + path = buf; + else + throw Poco::SystemException("Cannot get path of the current process."); +#elif POCO_OS == POCO_OS_NET_BSD + std::size_t size = sizeof(buf); + int n = readlink("/proc/curproc/exe", buf, size); + if (n > 0 && n < PATH_MAX) + path = buf; +#elif POCO_OS == POCO_OS_SOLARIS + char * execName = getexecname(); + if (execName) + path = execName; + else + throw Poco::SystemException("Cannot get path of the current process."); +#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID + const std::size_t size = sizeof(buf); + int n = readlink("/proc/self/exe", buf, size); + if (n > 0 && n < PATH_MAX) + path = buf; + else + throw Poco::SystemException("Cannot get path of the current process."); +#else + throw Poco::NotImplementedException("File path of the current process not implemented on this platform."); +#endif + + return path; +} + std::string PathImpl::currentImpl() { diff --git a/Foundation/src/Path_WIN32U.cpp b/Foundation/src/Path_WIN32U.cpp index db8e6cd25a..1643864651 100644 --- a/Foundation/src/Path_WIN32U.cpp +++ b/Foundation/src/Path_WIN32U.cpp @@ -19,9 +19,22 @@ #include "Poco/Exception.h" #include "Poco/UnWindows.h" - namespace Poco { +std::string PathImpl::selfImpl() +{ + std::string path; + Buffer buf(MAX_PATH_LEN); + DWORD n = GetModuleFileNameW(NULL, buf.begin(), MAX_PATH_LEN); + + if (n > 0 && n < MAX_PATH_LEN) + { + UnicodeConverter::toUTF8(buf.begin(), path); + return path; + } + + throw SystemException("Cannot get path of the current process."); +} std::string PathImpl::currentImpl() { diff --git a/Foundation/src/Path_WINCE.cpp b/Foundation/src/Path_WINCE.cpp index 05d9c868cf..7f2ba07397 100644 --- a/Foundation/src/Path_WINCE.cpp +++ b/Foundation/src/Path_WINCE.cpp @@ -23,6 +23,10 @@ namespace Poco { +std::string PathImpl::selfImpl() +{ + return(""); +} std::string PathImpl::currentImpl() { diff --git a/Foundation/testsuite/src/PathTest.cpp b/Foundation/testsuite/src/PathTest.cpp index c68e5bd693..fc0af68444 100644 --- a/Foundation/testsuite/src/PathTest.cpp +++ b/Foundation/testsuite/src/PathTest.cpp @@ -1619,6 +1619,30 @@ void PathTest::testWindowsSystem() #endif } +void PathTest::testSelf() +{ + std::string self = Path::self(); + std::cout << self << std::endl; + +#if POCO_OS == POCO_OS_MAC_OS_X \ + || POCO_OS == POCO_OS_FREE_BSD \ + || POCO_OS == POCO_OS_NET_BSD \ + || POCO_OS == POCO_OS_SOLARIS \ + || POCO_OS == POCO_OS_LINUX \ + || POCO_OS == POCO_OS_ANDROID \ + || POCO_OS == POCO_OS_WINDOWS_NT + + assertTrue(!self.empty()); + Path p(self); + + assertTrue(p.isAbsolute()); + assertTrue(p.isFile()); + assertTrue(self.find("testrunner") != std::string::npos); +#else + std::cout << "Path::self() not implemented for this platform." +#endif +} + void PathTest::setUp() { @@ -1662,6 +1686,7 @@ CppUnit::Test* PathTest::suite() CppUnit_addTest(pSuite, PathTest, testResolve); CppUnit_addTest(pSuite, PathTest, testPushPop); CppUnit_addTest(pSuite, PathTest, testWindowsSystem); + CppUnit_addTest(pSuite, PathTest, testSelf); return pSuite; } diff --git a/Foundation/testsuite/src/PathTest.h b/Foundation/testsuite/src/PathTest.h index 85264825d2..f05f224b43 100644 --- a/Foundation/testsuite/src/PathTest.h +++ b/Foundation/testsuite/src/PathTest.h @@ -52,6 +52,7 @@ class PathTest: public CppUnit::TestCase void testResolve(); void testPushPop(); void testWindowsSystem(); + void testSelf(); void setUp(); void tearDown();