program_location_impl.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright Antony Polukhin, 2015-2025.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
  8. #define BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
  9. #include <boost/dll/config.hpp>
  10. #include <boost/dll/detail/system_error.hpp>
  11. #include <boost/predef/os.h>
  12. #ifdef BOOST_HAS_PRAGMA_ONCE
  13. # pragma once
  14. #endif
  15. #if BOOST_OS_MACOS || BOOST_OS_IOS
  16. #include <string>
  17. #include <mach-o/dyld.h>
  18. namespace boost { namespace dll { namespace detail {
  19. inline boost::dll::fs::path program_location_impl(std::error_code &ec) {
  20. ec.clear();
  21. char path[1024];
  22. uint32_t size = sizeof(path);
  23. if (_NSGetExecutablePath(path, &size) == 0)
  24. return boost::dll::fs::path(path);
  25. std::string p;
  26. p.resize(size);
  27. if (_NSGetExecutablePath(&p[0], &size) != 0) {
  28. ec = std::make_error_code(
  29. std::errc::bad_file_descriptor
  30. );
  31. }
  32. return boost::dll::fs::path(std::move(p));
  33. }
  34. }}} // namespace boost::dll::detail
  35. #elif BOOST_OS_SOLARIS
  36. #include <stdlib.h>
  37. namespace boost { namespace dll { namespace detail {
  38. inline boost::dll::fs::path program_location_impl(std::error_code& ec) {
  39. ec.clear();
  40. return boost::dll::fs::path(getexecname());
  41. }
  42. }}} // namespace boost::dll::detail
  43. #elif BOOST_OS_BSD_FREE
  44. #include <string>
  45. #include <sys/types.h>
  46. #include <sys/sysctl.h>
  47. #include <stdlib.h>
  48. namespace boost { namespace dll { namespace detail {
  49. inline boost::dll::fs::path program_location_impl(std::error_code& ec) {
  50. ec.clear();
  51. int mib[4];
  52. mib[0] = CTL_KERN;
  53. mib[1] = KERN_PROC;
  54. mib[2] = KERN_PROC_PATHNAME;
  55. mib[3] = -1;
  56. char path[1024];
  57. size_t size = sizeof(path);
  58. if (sysctl(mib, 4, path, &size, nullptr, 0) == 0) {
  59. return boost::dll::fs::path(path);
  60. }
  61. const auto errno_snapshot = static_cast<std::errc>(errno);
  62. if (errno_snapshot != std::errc::not_enough_memory) {
  63. ec = std::make_error_code(
  64. errno_snapshot
  65. );
  66. }
  67. std::string p;
  68. p.resize(size);
  69. if (sysctl(mib, 4, p.data(), &size, nullptr, 0) != 0) {
  70. ec = std::make_error_code(
  71. static_cast<std::errc>(errno)
  72. );
  73. }
  74. return boost::dll::fs::path(std::move(p));
  75. }
  76. }}} // namespace boost::dll::detail
  77. #elif BOOST_OS_BSD_NET
  78. namespace boost { namespace dll { namespace detail {
  79. inline boost::dll::fs::path program_location_impl(std::error_code &ec) {
  80. boost::dll::fs::error_code fs_errc;
  81. auto result = boost::dll::fs::read_symlink("/proc/curproc/exe", fs_errc);
  82. ec = fs_errc;
  83. return result;
  84. }
  85. }}} // namespace boost::dll::detail
  86. #elif BOOST_OS_BSD_DRAGONFLY
  87. namespace boost { namespace dll { namespace detail {
  88. inline boost::dll::fs::path program_location_impl(std::error_code &ec) {
  89. boost::dll::fs::error_code fs_errc;
  90. auto result = boost::dll::fs::read_symlink("/proc/curproc/file", fs_errc);
  91. ec = fs_errc;
  92. return result;
  93. }
  94. }}} // namespace boost::dll::detail
  95. #elif BOOST_OS_QNX
  96. #include <fstream>
  97. #include <string> // for std::getline
  98. namespace boost { namespace dll { namespace detail {
  99. inline boost::dll::fs::path program_location_impl(std::error_code &ec) {
  100. ec.clear();
  101. std::string path;
  102. std::ifstream ifs("/proc/self/exefile");
  103. std::getline(ifs, path);
  104. if (ifs.fail() || path.empty()) {
  105. ec = std::make_error_code(
  106. std::errc::bad_file_descriptor
  107. );
  108. }
  109. return boost::dll::fs::path(std::move(path));
  110. }
  111. }}} // namespace boost::dll::detail
  112. #else // BOOST_OS_LINUX || BOOST_OS_UNIX || BOOST_OS_HPUX || BOOST_OS_ANDROID
  113. namespace boost { namespace dll { namespace detail {
  114. inline boost::dll::fs::path program_location_impl(std::error_code &ec) {
  115. // We can not use
  116. // boost::dll::detail::path_from_handle(dlopen(NULL, RTLD_LAZY | RTLD_LOCAL), ignore);
  117. // because such code returns empty path.
  118. boost::dll::fs::error_code fs_errc;
  119. auto result = boost::dll::fs::read_symlink("/proc/self/exe", fs_errc); // Linux specific
  120. ec = fs_errc;
  121. return result;
  122. }
  123. }}} // namespace boost::dll::detail
  124. #endif
  125. #endif // BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP