1+ #include < link.h>
2+ #include < cstdlib>
3+ #include < regex.h>
4+ #include < cstring>
5+ #include < libconfig.h>
6+
7+ #ifdef __cplusplus
8+ extern " C"
9+ {
10+ #endif
11+
12+ #include " common.h"
13+ #include " common/string_utils.h"
14+
15+ #ifdef __cplusplus
16+ }
17+ #endif
18+
19+ typedef struct {
20+ regex_t regex;
21+ char * version;
22+ } extract_libstdcpp_version_ctx_t ;
23+
24+ static int extract_libstdcpp_version (struct dl_phdr_info * info, size_t , void * data) {
25+ regmatch_t match[2 ] = {0x0 };
26+ auto * ctx = (extract_libstdcpp_version_ctx_t *) data;
27+ char * real_so_path = realpath (info->dlpi_name , nullptr );
28+
29+ if (real_so_path != NULL && regexec (&ctx->regex , real_so_path, 2 , match, 0 ) == 0 ) {
30+ char * version = strndup (real_so_path + match[1 ].rm_so , match[1 ].rm_eo - match[1 ].rm_so );
31+ ctx->version = version;
32+ return 1 ;
33+ }
34+
35+ return 0 ;
36+ }
37+
38+ char * extract_libstdcpp_version_from_runtime_libaries_paths () {
39+ extract_libstdcpp_version_ctx_t extract_libstdcpp_version_ctx = {nullptr };
40+
41+ if (regcomp (&extract_libstdcpp_version_ctx.regex , R"( libstdc\+\+\.so\.([0-9]+\.[0-9]+(\.[0-9]+)?))" ,
42+ REG_EXTENDED) != 0 ) {
43+ printf (" Regex compilation error." );
44+ exit (EXIT_FAILURE);
45+ }
46+
47+ // iterate over the loaded libraries to resolve their paths and guess the libstdc++ version from it
48+ dl_iterate_phdr (extract_libstdcpp_version, &extract_libstdcpp_version_ctx);
49+ return extract_libstdcpp_version_ctx.version ;
50+ }
51+
52+ char * read_required_glibstdcpp_version_from_config (char * config_path) {
53+ config_t cfg;
54+ const char * str;
55+
56+ config_init (&cfg);
57+
58+ /* Read the file. If there is an error, report it and exit. */
59+ if (!config_read_file (&cfg, config_path)) {
60+ fprintf (stderr, " ERROR:check-glibstdc++: %s:%d - %s\n " , config_error_file (&cfg), config_error_line (&cfg),
61+ config_error_text (&cfg));
62+ config_destroy (&cfg);
63+ exit (EXIT_FAILURE);
64+ }
65+
66+ if (!config_lookup_string (&cfg, " check.required_glibstdcpp" , &str)) {
67+ fprintf (stderr, " ERROR:check-glibstdc++: missing config entry 'check.required_glibstdcpp'" );
68+ exit (EXIT_FAILURE);
69+ }
70+
71+ char * glibstdcpp_version = strdup (str);
72+
73+ config_destroy (&cfg);
74+ return glibstdcpp_version;
75+ }
76+
77+ int main (int , char * []) {
78+ char * system_version = extract_libstdcpp_version_from_runtime_libaries_paths ();
79+
80+ char * config_path = resolve_module_config_path ();
81+ char * required_version = read_required_glibstdcpp_version_from_config (config_path);
82+
83+ // the libc module must be used if the system version is lesser than the required
84+ if (compare_version_strings (system_version, required_version) > 0 )
85+ return EXIT_SUCCESS;
86+ else
87+ return EXIT_FAILURE;
88+ }
0 commit comments