Coverage Report

Created: 2026-10-28 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Fast-DDS/src/cpp/utils/SystemInfo.hpp
Line
Count
Source
1
// Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef UTILS_SYSTEMINFO_HPP_
16
#define UTILS_SYSTEMINFO_HPP_
17
18
#if defined(_WIN32)
19
#include <process.h>
20
#else
21
#include <unistd.h>
22
#endif // if defined(_WIN32)
23
24
#include <cstdint>
25
#include <memory>
26
#include <mutex>
27
#include <string>
28
29
#include <fastdds/rtps/attributes/ThreadSettings.hpp>
30
#include <fastdds/dds/core/ReturnCode.hpp>
31
#include <fastdds/utils/IPFinder.hpp>
32
#include <utils/Host.hpp>
33
34
#if defined(_WIN32) || defined(__unix__)
35
#include <FileWatch.hpp>
36
#endif // defined(_WIN32) || defined(__unix__)
37
38
namespace eprosima {
39
40
using ReturnCode_t = eprosima::fastdds::dds::ReturnCode_t;
41
#if defined(_WIN32) || defined(__unix__)
42
using FileWatchHandle = std::unique_ptr<filewatch::FileWatch<std::string>>;
43
#else
44
using FileWatchHandle = void*;
45
#endif // defined(_WIN32) || defined(__unix__)
46
47
/**
48
 * This singleton serves as a centralized point from where to obtain platform dependent system information.
49
 */
50
class SystemInfo
51
{
52
public:
53
54
    /**
55
     * Get the identifier of the current process.
56
     *
57
     * @return the identifier of the current process.
58
     */
59
    inline int process_id() const
60
0
    {
61
#if defined(__cplusplus_winrt)
62
        return (int)GetCurrentProcessId();
63
#elif defined(_WIN32)
64
        return (int)_getpid();
65
#else
66
0
        return (int)getpid();
67
0
#endif // platform selection
68
0
    }
69
70
    /**
71
     * Get the identifier of the current host.
72
     *
73
     * @return the identifier of the current host.
74
     */
75
    inline uint16_t host_id() const
76
0
    {
77
0
        return Host::instance().id();
78
0
    }
79
80
    /**
81
     * Get the identifier of the current machine.
82
     *
83
     * @return the identifier of the current host.
84
     */
85
    inline fastcdr::string_255 machine_id() const
86
0
    {
87
0
        return Host::instance().machine_id();
88
0
    }
89
90
    /**
91
     * Get a reference to the singleton instance.
92
     *
93
     * @return reference to the singleton instance.
94
     */
95
    static const SystemInfo& instance()
96
0
    {
97
0
        static SystemInfo singleton;
98
99
0
        return singleton;
100
0
    }
101
102
    /**
103
     * Retrieve the value of a given environment variable if it exists.
104
     * The string which is returned in the env_value output parameter is not modified
105
     * if the environment variable is not set.
106
     *
107
     * This function is thread-safe as long as no other function modifies the host environment (in particular, POSIX
108
     * functions setenv, unsetenv and putenv would introduce a data race if called without synchronization.)
109
     *
110
     * \param [in] env_name name of the environment variable.
111
     * \param [out] env_value value of the environment variable.
112
     * @return RETCODE_OK if the environment variable is set.
113
     * RETCODE_NO_DATA if the environment variable is unset.
114
     * RETCODE_BAD_PARAMETER if the provided parameters are not valid.
115
     */
116
    static ReturnCode_t get_env(
117
            const std::string& env_name,
118
            std::string& env_value);
119
120
    /**
121
     * Read environment variable contained in the environment file.
122
     *
123
     * @param [in] filename path/name of the environment file.
124
     * @param [in] env_name environment variable name to read from the file.
125
     * @param [out] env_value environment variable value read from the file.
126
     *
127
     * @return RETCODE_OK if succesful.
128
     * RETCODE_BAD_PARAMETER if the file does not exist.
129
     * RETCODE_NO_DATA if the file exists but there is no information about the environment variable.
130
     * RETCODE_ERROR if the file is empty or malformed.
131
     */
132
    static ReturnCode_t get_env(
133
            const std::string& filename,
134
            const std::string& env_name,
135
            std::string& env_value);
136
137
    /**
138
     * Get the effective username of the person that launched the application
139
     * This implementation follows the whoami implementation for POSIX
140
     * (https://github.com/coreutils/coreutils/blob/master/src/whoami.c)
141
     *
142
     * geteuid is always successful.
143
     *
144
     * getpwuid returns a pointer to a struct passwd if a matching entry is found and nullptr otherwise.
145
     * This pointer is only valid until the next time getpwuid function is called, because it is a direct
146
     * pointer to the static storage.
147
     * Modifying the pointer invokes undefined behavior.
148
     *
149
     * This function is thread-safe as long as no other function modifies the storage areas pointed within the structure
150
     * (in particular, POSIX functions getpwent or getpwnam might overwrite some of the storage areas.)
151
     *
152
     * \param [out] username string with the effective username.
153
     * @return RETCODE_OK if successful.
154
     * RETCODE_ERROR if the username information cannot be determined.
155
     */
156
    static ReturnCode_t get_username(
157
            std::string& username);
158
159
    /**
160
     * Check if the file with name \c filename exists.
161
     * \c filename can also include the path to the file.
162
     *
163
     * \param [in] filename path/name of the file to check.
164
     * @return True if the file exists. False otherwise.
165
     */
166
    static bool file_exists(
167
            const std::string& filename);
168
169
    /**
170
     * Wait for file with name \c filename
171
     * until exclusive lock can be taken on it
172
     *
173
     * \param [in] filename path/name of the file to check.
174
     * \param [in] lock wait timeout
175
     * @return True if the file could be locked. False otherwise (timeout).
176
     */
177
    static bool wait_for_file_closure(
178
            const std::string& filename,
179
            const std::chrono::seconds timeout);
180
181
    /**
182
     * Read FASTDDS_ENVIRONMENT_FILE_ENV_VAR environment value and save its value.
183
     * Use get_environment_file to read its value.
184
     *
185
     * @return RETCODE_OK if the environment variable is set.
186
     * RETCODE_NO_DATA if the environment variable is unset.
187
     */
188
    static ReturnCode_t set_environment_file();
189
190
    /**
191
     * Getter for the path/filename contained in the FASTDDS_ENVIRONMENT_FILE_ENV_VAR.
192
     * The value is set calling set_environment_file().
193
     *
194
     * @return Path/filename contained in the environment variable.
195
     */
196
    static const std::string& get_environment_file();
197
198
    /**
199
     * Start a thread that watches for changes in the given file and executes a callback when the file changes.
200
     *
201
     * The method returns a handle to the object that implements the watcher containing the thread.
202
     * The scope of the listening thread is the same as the watching object, so when the object
203
     * goes out of scope, the thread is terminated.
204
     *
205
     * The thread can be terminated earlier with stop_watching_file(FileWatchHandle)
206
     *
207
     * @param [in] filename Path/name of the file to watch.
208
     * @param [in] callback Callback to execute when the file changes.
209
     * @param [in] watch_thread_config Thread settings for watch thread.
210
     * @param [in] callback_thread_config Thread settings for callback thread.
211
     *
212
     * @return The handle that represents the watcher object.
213
     */
214
    static FileWatchHandle watch_file(
215
            std::string filename,
216
            std::function<void()> callback,
217
            const fastdds::rtps::ThreadSettings& watch_thread_config,
218
            const fastdds::rtps::ThreadSettings& callback_thread_config);
219
220
    /**
221
     * Stop a file watcher.
222
     *
223
     * This method effectively destroys the file watcher and the thread that were created with watch_file.
224
     * Once this method returns, the handle is no longer valid.
225
     *
226
     * @param [in] handle The watcher handle as returned by watch_file.
227
     */
228
    static void stop_watching_file(
229
            FileWatchHandle& handle);
230
231
    /**
232
     * Get the current time as string, formatting it as specified by argument format.
233
     *
234
     * The function returns a timestamp of the current time in the following format: YYYY-MM-DD HH:MM:SS.ms
235
     *
236
     * @param [in] format Format of the date to be printed.
237
     * This format is build according to the std::put_time(const struct tm* tmb, const charT* fmt) function.
238
     * Default "%F %T".
239
     *
240
     * @return The current time in string format
241
     */
242
    static std::string get_timestamp(
243
            const char* format = "%F %T");
244
245
    /**
246
     * Fetch and store/update the information relative to all network interfaces present on the system.
247
     *
248
     * @return true if successful, false otherwise
249
     */
250
    static bool update_interfaces();
251
252
    /**
253
     * Get the information relative to all network interfaces present on the system.
254
     *
255
     * The loopback interface is only included in the collection if \c return_loopback is true.
256
     * If this information is already cached, it is returned without performing any system call,
257
     * unless \c force_lookup is true.
258
     *
259
     * @param [out] vec_name Collection to be populated with the network interfaces information.
260
     * @param [in] return_loopback Whether to include the loopback interface in the collection.
261
     * @param [in] force_lookup Whether to force a system call even if information is cached.
262
     *
263
     * @return true if successful, false otherwise
264
     */
265
    static bool get_ips(
266
            std::vector<fastdds::rtps::IPFinder::info_IP>& vec_name,
267
            bool return_loopback,
268
            bool force_lookup);
269
270
private:
271
272
    SystemInfo();
273
274
    static std::string environment_file_;
275
276
    static bool cached_interfaces_;
277
    static std::vector<fastdds::rtps::IPFinder::info_IP> interfaces_;
278
    static std::mutex interfaces_mtx_;
279
};
280
281
/**
282
 * Environment variable to specify the name of a file (including or not the path) where the environment variables
283
 * could be defined.
284
 * Thus, the user can modify the environment variables' values in runtime.
285
 *
286
 * TODO(jlbueno) Currently only ROS_DISCOVERY_SERVER environment variable is supported.
287
 */
288
const char* const FASTDDS_ENVIRONMENT_FILE_ENV_VAR = "FASTDDS_ENVIRONMENT_FILE";
289
290
} // namespace eprosima
291
292
#endif // UTILS_SYSTEMINFO_HPP_