2222#include " er/Flags.h"
2323
2424#include " Array.h"
25- #include " Environment.h"
2625#include " Logger.h"
27- #include " Paths .h"
26+ #include " PathResolver .h"
2827#include " Resolver.h"
2928#include " Session.h"
3029
3130#include < algorithm>
3231#include < cerrno>
33- #include < climits>
34- #include < string_view>
35-
36- #include < unistd.h>
3732
3833namespace {
3934
40- constexpr char DIR_SEPARATOR = ' /' ;
41-
4235 constexpr el::log::Logger LOGGER (" Executor.cc" );
4336
4437 constexpr el::Executor::Result failure (int const error_code) noexcept
@@ -71,10 +64,10 @@ namespace {
7164 : session(session)
7265 , path(path)
7366 , argv(argv)
74- {
75- }
67+ { }
7668
77- [[nodiscard]] constexpr size_t length () const noexcept
69+ [[nodiscard]]
70+ constexpr size_t length () const noexcept
7871 {
7972 return (session.verbose ? 6 : 7 ) + el::array::length (argv) + 1 ;
8073 }
@@ -99,7 +92,8 @@ namespace {
9992 *it = nullptr ;
10093 }
10194
102- [[nodiscard]] constexpr const char * file () const noexcept
95+ [[nodiscard]]
96+ constexpr const char * file () const noexcept
10397 {
10498 return session.reporter ;
10599 }
@@ -109,114 +103,6 @@ namespace {
109103 const char * path;
110104 char * const * const argv;
111105 };
112-
113- class PathResolver {
114- public:
115- struct Result {
116- const char * return_value;
117- const int error_code;
118-
119- constexpr explicit operator bool () const noexcept {
120- return (return_value != nullptr ) && (error_code == 0 );
121- }
122- };
123-
124- public:
125- explicit PathResolver (el::Resolver const &resolver);
126-
127- Result from_current_directory (std::string_view const &file);
128- Result from_path (std::string_view const &file, char * const * envp);
129- Result from_search_path (std::string_view const &file, const char *search_path);
130-
131- PathResolver (PathResolver const &) = delete ;
132- PathResolver (PathResolver &&) noexcept = delete ;
133-
134- PathResolver &operator =(PathResolver const &) = delete ;
135- PathResolver &&operator =(PathResolver &&) noexcept = delete ;
136-
137- private:
138- static bool contains_dir_separator (std::string_view const &candidate);
139-
140- private:
141- el::Resolver const &resolver_;
142- char result_[PATH_MAX];
143- };
144-
145- PathResolver::PathResolver (const el::Resolver &resolver)
146- : resolver_(resolver)
147- , result_()
148- { }
149-
150- PathResolver::Result PathResolver::from_current_directory (std::string_view const &file) {
151- // create absolute path to the given file.
152- if (nullptr == resolver_.realpath (file.begin (), result_)) {
153- return PathResolver::Result {nullptr , ENOENT };
154- }
155- // check if it's okay to execute.
156- if (0 == resolver_.access (result_, X_OK)) {
157- return PathResolver::Result { result_, 0 };
158- }
159- // try to set a meaningful error value.
160- if (0 == resolver_.access (result_, F_OK)) {
161- return PathResolver::Result {nullptr , EACCES };
162- }
163- return PathResolver::Result {nullptr , ENOENT };
164- }
165-
166- PathResolver::Result PathResolver::from_path (std::string_view const &file, char * const * envp) {
167- if (contains_dir_separator (file)) {
168- // the file contains a dir separator, it is treated as path.
169- return from_current_directory (file);
170- } else {
171- // otherwise use the PATH variable to locate the executable.
172- const char *paths = el::env::get_env_value (const_cast <const char **>(envp), " PATH" );
173- if (paths != nullptr ) {
174- return from_search_path (file, paths);
175- }
176- // fall back to `confstr` PATH value if the environment has no value.
177- const size_t search_path_length = resolver_.confstr (_CS_PATH, nullptr , 0 );
178- if (search_path_length != 0 ) {
179- char search_path[search_path_length];
180- if (resolver_.confstr (_CS_PATH, search_path, search_path_length) != 0 ) {
181- return from_search_path (file, search_path);
182- }
183- }
184- return PathResolver::Result {nullptr , ENOENT };
185- }
186- }
187-
188- PathResolver::Result PathResolver::from_search_path (std::string_view const &file, const char *search_path) {
189- if (contains_dir_separator (file)) {
190- // the file contains a dir separator, it is treated as path.
191- return from_current_directory (file);
192- } else {
193- // otherwise use the given search path to locate the executable.
194- for (auto path : el::Paths (search_path)) {
195- // ignore empty entries
196- if (path.empty ()) {
197- continue ;
198- }
199- // create a path
200- char candidate[PATH_MAX];
201- {
202- auto it = el::array::copy (path.begin (), path.end (), candidate, candidate + PATH_MAX);
203- *it++ = DIR_SEPARATOR;
204- it = el::array::copy (file.begin (), file.end (), it, candidate + PATH_MAX);
205- *it = 0 ;
206- }
207- // check if it's okay to execute.
208- if (auto result = from_current_directory (candidate); result) {
209- return result;
210- }
211- }
212- // if all attempt were failing, then quit with a failure.
213- return PathResolver::Result {nullptr , ENOENT };
214- }
215- }
216-
217- bool PathResolver::contains_dir_separator (std::string_view const &candidate) {
218- return std::find (candidate.begin (), candidate.end (), DIR_SEPARATOR) != candidate.end ();
219- }
220106}
221107
222108#pragma GCC diagnostic push
0 commit comments