• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.27
/libs/core/prefix/src/find_prefix.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
//  Copyright (c) 2012 Bryce Adelstein-Lelbach
3
//  Copyright (c) 2012-2025 Hartmut Kaiser
4
//
5
//  SPDX-License-Identifier: BSL-1.0
6
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
7
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
////////////////////////////////////////////////////////////////////////////////
9

10
#include <hpx/config.hpp>
11
#include <hpx/modules/errors.hpp>
12
#include <hpx/modules/filesystem.hpp>
13
#include <hpx/modules/plugin.hpp>
14
#include <hpx/modules/string_util.hpp>
15
#include <hpx/modules/type_support.hpp>
16
#include <hpx/prefix/find_prefix.hpp>
17

18
#if defined(HPX_WINDOWS)
19
#include <windows.h>
20
#elif defined(__linux) || defined(linux) || defined(__linux__)
21
#include <linux/limits.h>
22
#include <sys/stat.h>
23
#include <unistd.h>
24
#include <vector>
25
#elif __APPLE__
26
#include <mach-o/dyld.h>
27
#elif defined(__FreeBSD__)
28
#include <algorithm>
29
#include <iterator>
30
#include <sys/sysctl.h>
31
#include <sys/types.h>
32
#include <vector>
33
#endif
34

35
#include <cstdint>
36
#include <string>
37

38
namespace hpx::util {
39

40
    static char const* prefix_ = nullptr;
41

42
    void set_hpx_prefix(char const* prefix) noexcept
43
    {
44
        if (prefix_ == nullptr)
64✔
45
        {
46
            prefix_ = prefix;
64✔
47
        }
48
    }
64✔
49

50
    char const* hpx_prefix() noexcept
64✔
51
    {
52
        return prefix_;
1,221✔
53
    }
54

1,221✔
55
    std::string find_prefix(std::string const& library)
56
    {
57
#if !defined(__ANDROID__) && !defined(ANDROID) && !defined(__MIC)
1,216✔
58
        try
59
        {
60
            error_code ec(hpx::throwmode::lightweight);
61
            hpx::util::plugin::dll dll(HPX_MAKE_DLL_STRING(library));
62

63
            dll.load_library(ec);
3,648✔
64
            if (ec)
65
                return hpx_prefix();
66

1,216✔
67
            using hpx::filesystem::path;
1,216✔
68

69
            std::string prefix =
70
                path(dll.get_directory(ec)).parent_path().string();
71

72
            if (ec || prefix.empty())
×
73
                return hpx_prefix();
74

×
75
            return prefix;
×
76
        }
77
        // NOLINTNEXTLINE(bugprone-empty-catch)
×
78
        catch (std::logic_error const&)
1,216✔
79
        {
×
80
            // just ignore loader problems
81
        }
82
#endif
×
83
        return hpx_prefix();
84
    }
×
85

86
    std::string find_prefixes(
87
        std::string const& suffix, std::string const& library)
955✔
88
    {
89
        std::string prefixes = find_prefix(library);
90

955✔
91
        hpx::string_util::char_separator sep(HPX_INI_PATH_DELIMITER);
92
        hpx::string_util::tokenizer tokens(prefixes, sep);
955✔
93
        std::string result;
94
        for (auto it = tokens.begin(); it != tokens.end(); ++it)
95
        {
955✔
96
            if (it != tokens.begin())
97
            {
×
98
                result += HPX_INI_PATH_DELIMITER;
99
            }
100
            result += *it;
101
            result += suffix;
102

103
#if defined(HPX_MSVC)
104
            result += HPX_INI_PATH_DELIMITER;
105
            result += *it;
106
            result += "/bin";
107
#endif
108

109
            result += HPX_INI_PATH_DELIMITER;
110
            result += *it;
111
#if defined(HPX_MSVC)
112
            result += "/bin";
113
#else
114
            result += "/lib";
115
#endif
116
            result += suffix;
117
        }
118
        return result;
955✔
119
    }
955✔
120

121
    ///////////////////////////////////////////////////////////////////////////////
122
    std::string get_executable_prefix(char const* argv0)
123
    {
256✔
124
        using hpx::filesystem::path;
125
        path const p(get_executable_filename(argv0));
126

256✔
127
        return p.parent_path().parent_path().string();
128
    }
768✔
129

256✔
130
    std::string get_executable_filename(char const* argv0)
131
    {
256✔
132
        std::string r;
133

134
#if defined(HPX_WINDOWS)
135
        HPX_UNUSED(argv0);
136

137
        char exe_path[MAX_PATH + 1] = {'\0'};
138
        if (!GetModuleFileNameA(nullptr, exe_path, sizeof(exe_path)))
139
        {
140
            HPX_THROW_EXCEPTION(hpx::error::dynamic_link_failure,
141
                "get_executable_filename",
142
                "unable to find executable filename");
143
        }
144
        r = exe_path;
145

146
#elif defined(__linux) || defined(linux) || defined(__linux__)
147
        char buf[PATH_MAX + 1];
148
        ssize_t length = ::readlink("/proc/self/exe", buf, sizeof(buf));
149

256✔
150
        if (length != -1)
151
        {
256✔
152
            buf[length] = '\0';
153
            r = buf;
256✔
154
            return r;
155
        }
256✔
156

157
        std::string argv0_(argv0);
158

×
159
        // REVIEW: Should we resolve symlinks at any point here?
160
        if (argv0_.length() > 0)
161
        {
×
162
            // Check for an absolute path.
163
            if (argv0_[0] == '/')
164
                return argv0_;
×
165

×
166
            // Check for a relative path.
167
            if (argv0_.find('/') != std::string::npos)
168
            {
×
169
                // Get the current working directory.
170

171
                // NOTE: getcwd does give you a null terminated string,
172
                // while readlink (above) does not.
173
                if (::getcwd(buf, PATH_MAX))
174
                {
×
175
                    r = buf;
176
                    r += '/';
177
                    r += argv0_;
178
                    return r;
179
                }
×
180
            }
181

182
            // Search PATH
183
            char const* epath = ::getenv("PATH");
184
            if (epath)
×
185
            {
×
186
                std::vector<std::string> path_dirs;
187

×
188
                hpx::string_util::split(path_dirs, epath,
189
                    hpx::string_util::is_any_of(":"),
×
190
                    hpx::string_util::token_compress_mode::on);
×
191

192
                for (std::uint64_t i = 0; i < path_dirs.size(); ++i)
193
                {
×
194
                    r = path_dirs[i];
195
                    r += '/';
196
                    r += argv0_;
197

198
                    // Can't use Boost.Filesystem as it doesn't let me access
199
                    // st_uid and st_gid.
200
                    struct stat s;
201

202
                    // Make sure the file is executable and shares our
203
                    // effective uid and gid.
204
                    // NOTE: If someone was using an HPX application that was
205
                    // seteuid'd to root, this may fail.
206
                    if (0 == ::stat(r.c_str(), &s))
207
                        if ((s.st_uid == ::geteuid()) &&
×
208
                            (s.st_mode & S_IXUSR) &&
×
209
                            (s.st_gid == ::getegid()) &&
×
210
                            (s.st_mode & S_IXGRP) && (s.st_mode & S_IXOTH))
×
211
                            return r;
×
212
                }
×
213
            }
214
        }
×
215

216
        HPX_THROW_EXCEPTION(hpx::error::dynamic_link_failure,
217
            "get_executable_filename", "unable to find executable filename");
×
218

219
#elif defined(__APPLE__)
220
        HPX_UNUSED(argv0);
221

222
        char exe_path[PATH_MAX + 1];
223
        std::uint32_t len = sizeof(exe_path) / sizeof(exe_path[0]);
224

225
        if (0 != _NSGetExecutablePath(exe_path, &len))
226
        {
227
            HPX_THROW_EXCEPTION(hpx::error::dynamic_link_failure,
228
                "get_executable_filename",
229
                "unable to find executable filename");
230
        }
231
        exe_path[len - 1] = '\0';
232
        r = exe_path;
233

234
#elif defined(__FreeBSD__)
235
        HPX_UNUSED(argv0);
236

237
        int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
238
        size_t cb = 0;
239
        sysctl(mib, 4, nullptr, &cb, nullptr, 0);
240
        if (cb)
241
        {
242
            std::vector<char> buf(cb);
243
            sysctl(mib, 4, &buf[0], &cb, nullptr, 0);
244
            std::copy(buf.begin(), buf.end(), std::back_inserter(r));
245
        }
246

247
#else
248
#error Unsupported platform
249
#endif
250

251
        return r;
252
    }
253
}    // namespace hpx::util
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc