jaulib v1.3.0
Jau Support Library (C++, Java, ..)
native_lib.hpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#pragma once
25
26#include <cstdint>
27#include <string>
28
29#include "jau/debug.hpp"
30#include "jau/string_util.hpp"
31
33#include "jau/os/dyn_linker.hpp"
34
35namespace jau::os {
36
37 /** \addtogroup OSSup
38 *
39 * @{
40 */
41
42
43 /** Runtime libary dynamic library (RTLD) access. */
45 private:
46 DynamicLinker& m_dynLink;
47
48 DynamicLinker::libhandle_t m_libraryHandle;
49
50 // May as well keep around the path to the library we opened
51 std::string m_libraryPath;
52
53 bool m_global;
54
55 // Native library path of the opened native libraryHandle, maybe null
56 std::string m_nativeLibraryPath;
57
58 static std::string getNativeLibPath(DynamicLinker& dl, DynamicLinker::libhandle_t libraryHandle,
59 const std::string& libraryPath, const std::string& symbolName) {
60 if( nullptr == libraryHandle ) {
61 return "";
62 } else {
63 const char *nlp = dl.lookupLibraryPathname(libraryHandle, symbolName);
64 if( nullptr != nlp ) {
65 return std::string(nlp);
66 } else {
67 return libraryPath;
68 }
69 }
70 }
71
72 // Private constructor to prevent arbitrary instances from floating around
73 NativeLibrary(DynamicLinker& dl, DynamicLinker::libhandle_t libraryHandle, const std::string& libraryPath, bool global, const std::string& symbolName)
74 : m_dynLink(dl), m_libraryHandle(libraryHandle), m_libraryPath(libraryPath), m_global(global),
75 m_nativeLibraryPath(getNativeLibPath(dl, libraryHandle, libraryPath, symbolName))
76 { }
77
78 public:
79
80 DynamicLinker::symhandle_t dynamicLookupFunction(const std::string& funcName) const noexcept override {
81 return m_dynLink.lookupSymbol(m_libraryHandle, funcName);
82 }
83
84 DynamicLinker::symhandle_t dynamicLookupFunctionGlobal(const std::string& funcName) const noexcept override {
85 return m_dynLink.lookupSymbolGlobal(funcName);
86 }
87
88 /** Returns the used DynamicLinker reference. */
89 DynamicLinker& dynamicLinker() const noexcept { return m_dynLink; }
90
91 /**
92 * Returns true if this instance is valid, i.e. native library successfully opened once but not necessarily isOpen() now.
93 * @see resolvedLibraryPath()
94 */
95 bool isValid() const noexcept { return m_nativeLibraryPath.size() > 0; }
96
97 /** Returns true if this instance isValid() and not close()'ed, otherwise false. */
98 bool isOpen() const noexcept { return nullptr != m_libraryHandle; }
99
100 /** Returns the native library handle if valid and not closed, otherwise nullptr. */
101 DynamicLinker::libhandle_t libraryHandle() const noexcept { return m_libraryHandle; }
102
103 /** Returns the path of the opened native library file. */
104 const std::string& libraryPath() const noexcept { return m_libraryPath; }
105
106 /**
107 * Returns the resolved native path of the opened native library, might be libraryPath() if not supported by OS.
108 *
109 * If this native library is not isValid(), method returns an empty string.
110 * @see isValid()
111 */
112 const std::string& resolvedLibraryPath() const noexcept { return m_nativeLibraryPath; }
113
114 /** Closes this native library. Further lookup operations are not allowed after calling this method. */
115 void close() noexcept {
116 DBG_PRINT("NativeLibrary.close(): closing %s", toString().c_str());
117 if ( nullptr != m_libraryHandle ) {
118 const DynamicLinker::libhandle_t handle = m_libraryHandle;
119 m_libraryHandle = nullptr;
120 m_dynLink.closeLibrary(handle);
121 DBG_PRINT("NativeLibrary.close(): Successfully closed %s", toString().c_str());
122 }
123 }
124
125 std::string toString() const noexcept {
126 if( isValid() ) {
127 return "NativeLibrary[path[given '" + m_libraryPath + "', native '"+m_nativeLibraryPath+"'], 0x" +
128 jau::to_hexstring(m_libraryHandle) + ", global " + std::to_string(m_global) + "]";
129 } else {
130 return "NativeLibrary[invalid, path[given '" + m_libraryPath + "'], 0x" +
131 jau::to_hexstring(m_libraryHandle) + ", global " + std::to_string(m_global) + "]";
132 }
133 }
134
135 /**
136 * Opens the given native library, assuming it has the same base name on all platforms.
137 *
138 * The {@code searchSystemPath} argument changes the behavior to
139 * either use the default system path or not at all.
140 *
141 * Assuming {@code searchSystemPath} is {@code true},
142 * the {@code searchSystemPathFirst} argument changes the behavior to first
143 * search the default system path rather than searching it last.
144 *
145 * @param libName library name, with or without prefix and suffix
146 * @param searchSystemPath if {@code true} library shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
147 * @param searchSystemPathFirst if {@code true} system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
148 * if {@code searchSystemPath} is {@code false} this argument is ignored.
149 * @param global if {@code true} allows system wide access of the loaded library, otherwise access is restricted to the process.
150 * @return {@link NativeLibrary} instance, use isValid() to check whether the native library was loaded successful.
151 */
152 static NativeLibrary open(const std::string& libName,
153 const bool searchSystemPath,
154 const bool searchSystemPathFirst,
155 const bool global) noexcept {
156 return open(libName, searchSystemPath, searchSystemPathFirst, global, "");
157 }
158
159 /**
160 * Opens the given native library, assuming it has the same base name on all platforms.
161 *
162 * The {@code searchSystemPath} argument changes the behavior to
163 * either use the default system path or not at all.
164 *
165 * Assuming {@code searchSystemPath} is {@code true},
166 * the {@code searchSystemPathFirst} argument changes the behavior to first
167 * search the default system path rather than searching it last.
168 *
169 * @param libName library name, with or without prefix and suffix
170 * @param searchSystemPath if {@code true} library shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
171 * @param searchSystemPathFirst if {@code true} system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
172 * if {@code searchSystemPath} is {@code false} this argument is ignored.
173 * @param loader {@link ClassLoader} to locate the library
174 * @param global if {@code true} allows system wide access of the loaded library, otherwise access is restricted to the process.
175 * @param symbolName optional symbol name for an OS which requires the symbol's address to retrieve the path of the containing library
176 * @return {@link NativeLibrary} instance, use isValid() to check whether the native library was loaded successful.
177 * @throws SecurityException if user is not granted access for the named library.
178 * @since 2.4.0
179 */
180 static NativeLibrary open(const std::string& libName,
181 const bool searchSystemPath,
182 const bool searchSystemPathFirst,
183 const bool global, const std::string& symbolName) noexcept {
184 std::vector<std::string> paths = DynamicLinker::enumerateLibraryPaths(libName, searchSystemPath, searchSystemPathFirst);
185
186 DynamicLinker& m_dynLink = DynamicLinker::get();
187
188 // Iterate down these and see which one if any we can actually find.
189 for (const std::string& path : paths ) {
190 DBG_PRINT("NativeLibrary.open(global %d): Trying to load %s", global, path.c_str());
192 if(global) {
193 res = m_dynLink.openLibraryGlobal(path);
194 } else {
195 res = m_dynLink.openLibraryLocal(path);
196 }
197 if ( 0 != res ) {
198 NativeLibrary nl(m_dynLink, res, path, global, symbolName);
199 DBG_PRINT("NativeLibrary.open: Opened: %s", nl.toString().c_str());
200 return nl;
201 } else if( jau::environment::get().debug ) {
202 DBG_PRINT("NativeLibrary.open: Failed to open '%s', last error %s",
203 path.c_str(), m_dynLink.getLastError().c_str());
204 }
205 }
206 DBG_PRINT("NativeLibrary.open(global %d): Did not succeed in loading: '%s' within '%s'",
207 global, libName.c_str(), jau::to_string(paths).c_str());
208 return NativeLibrary(m_dynLink, nullptr, libName, global, symbolName);
209 }
210 };
211
212 /**@}*/
213
214} // namespace jau::os
215
static environment & get(const std::string &root_prefix_domain="jau") noexcept
Static singleton initialization of this project's environment with the given global root prefix_domai...
Low level secure dynamic linker access.
Definition: dyn_linker.hpp:45
static DynamicLinker & get() noexcept
Returns static singleton instance of DynamicLinker.
Definition: dyn_linker.hpp:235
symhandle_t lookupSymbolGlobal(const std::string &symbolName) noexcept
Definition: dyn_linker.hpp:306
static std::vector< std::string > enumerateLibraryPaths(const std::string &libName, bool searchSystemPath=false, bool searchSystemPathFirst=false) noexcept
Returns list of potential absolute library filenames.
Definition: os_support.cpp:321
symhandle_t lookupSymbol(libhandle_t handle, const std::string &symbolName) noexcept
Definition: dyn_linker.hpp:320
void * symhandle_t
symbol handle within a library
Definition: dyn_linker.hpp:50
libhandle_t openLibraryGlobal(const std::string &pathname) noexcept
Opens the named library, allowing system wide access for other users.
Definition: dyn_linker.hpp:256
void * libhandle_t
library handle
Definition: dyn_linker.hpp:48
const char * lookupLibraryPathname(libhandle_t handle, const std::string &symbolName) noexcept
Definition: dyn_linker.hpp:293
std::string getLastError() noexcept
Returns a string containing the last error.
Definition: dyn_linker.hpp:353
libhandle_t openLibraryLocal(const std::string &pathname) noexcept
Opens the named library, restricting access to this process.
Definition: dyn_linker.hpp:275
void closeLibrary(libhandle_t handle) noexcept
Security checks are implicit by previous call of openLibraryLocal(const std::string_view&,...
Definition: dyn_linker.hpp:336
Interface callers may use ProcAddressHelper's reset helper method to install function pointers into a...
Runtime libary dynamic library (RTLD) access.
Definition: native_lib.hpp:44
DynamicLinker & dynamicLinker() const noexcept
Returns the used DynamicLinker reference.
Definition: native_lib.hpp:89
bool isValid() const noexcept
Returns true if this instance is valid, i.e.
Definition: native_lib.hpp:95
void close() noexcept
Closes this native library.
Definition: native_lib.hpp:115
DynamicLinker::symhandle_t dynamicLookupFunctionGlobal(const std::string &funcName) const noexcept override
Returns the function handle for function funcName gathered globally within all loaded libraries.
Definition: native_lib.hpp:84
const std::string & resolvedLibraryPath() const noexcept
Returns the resolved native path of the opened native library, might be libraryPath() if not supporte...
Definition: native_lib.hpp:112
const std::string & libraryPath() const noexcept
Returns the path of the opened native library file.
Definition: native_lib.hpp:104
DynamicLinker::symhandle_t dynamicLookupFunction(const std::string &funcName) const noexcept override
Returns the function handle for function funcName gathered within the associated native library.
Definition: native_lib.hpp:80
std::string toString() const noexcept
Definition: native_lib.hpp:125
DynamicLinker::libhandle_t libraryHandle() const noexcept
Returns the native library handle if valid and not closed, otherwise nullptr.
Definition: native_lib.hpp:101
bool isOpen() const noexcept
Returns true if this instance isValid() and not close()'ed, otherwise false.
Definition: native_lib.hpp:98
static NativeLibrary open(const std::string &libName, const bool searchSystemPath, const bool searchSystemPathFirst, const bool global, const std::string &symbolName) noexcept
Opens the given native library, assuming it has the same base name on all platforms.
Definition: native_lib.hpp:180
static NativeLibrary open(const std::string &libName, const bool searchSystemPath, const bool searchSystemPathFirst, const bool global) noexcept
Opens the given native library, assuming it has the same base name on all platforms.
Definition: native_lib.hpp:152
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition: debug.hpp:52
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
Definition: dyn_linker.hpp:37