1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
pub struct Version {
pub major: usize,
pub minor: usize,
}
#[cfg(all(target_os = "linux", target_env = "gnu"))]
mod imp {
use super::Version;
use std::process::Command;
use regex::Regex;
pub fn get_version() -> Result<Version, String> {
let output = Command::new("ldd")
.args(&["--version"])
.output()
.expect("failed to execute ldd");
let output_str = std::str::from_utf8(&output.stdout).unwrap();
let version_str = ldd_output_to_version_str(output_str)?;
parse_glibc_version(version_str)
.ok_or_else(|| format!("Invalid version string from ldd output: {}", version_str,))
}
fn ldd_output_to_version_str(output_str: &str) -> Result<&str, String> {
let version_reg = Regex::new(r#"ldd \(.+\) ([0-9]+\.[0-9]+)"#).unwrap();
if let Some(captures) = version_reg.captures(output_str) {
Ok(captures.get(1).unwrap().as_str())
} else {
Err(format!(
"ERROR: failed to detect glibc version. ldd output: {}",
output_str,
))
}
}
fn parse_glibc_version(version: &str) -> Option<Version> {
let mut parsed_ints = version.split('.').map(str::parse::<usize>).fuse();
match (parsed_ints.next(), parsed_ints.next()) {
(Some(Ok(major)), Some(Ok(minor))) => Some(Version { major, minor }),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_ldd_output() {
let ver_str = ldd_output_to_version_str(
r#"ldd (GNU libc) 2.12
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper."#,
)
.unwrap();
assert_eq!(ver_str, "2.12");
let ver_str = ldd_output_to_version_str(
r#"ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper."#,
)
.unwrap();
assert_eq!(ver_str, "2.31");
}
}
}
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
mod imp {
use super::Version;
pub fn get_version() -> Result<Version, String> {
unimplemented!();
}
}
#[inline]
pub fn get_version() -> Result<Version, String> {
imp::get_version()
}