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
//! > /proc/version
//! > This string identifies the kernel version that is currently
//! > running. It includes the contents of /proc/sys/kernel/ostype,
//! > /proc/sys/kernel/osrelease and /proc/sys/kernel/version. For
//! > example:
//! >
//! > Linux version 1.0.9 (quinlan@phaze) #1 Sat May 14 01:51:54 EDT 1994
//! >
//! > -- http://man7.org/linux/man-pages/man5/proc.5.html
define_struct! {
/// Represent the content of /proc/version
///
/// The fields of this struc reference to
/// [`scripts/mkcompile_h`](https://github.com/torvalds/linux/blob/master/scripts/mkcompile_h) and
/// [`init/version.c`](https://github.com/torvalds/linux/blob/master/init/version.c).
///
/// ```text
/// Linux version ${uts_release} (${linux_compiler_by}@${linux_compiler_host}) (${linux_compiler}) #${uts_version} ${config_flag} ${timestamp}
/// ```
pub struct Version {
uts_release: String,
linux_compiler_by: String,
linux_compiler_host: String,
linux_compiler: String,
uts_version: String,
config_flag: String,
timestamp: String,
}
}
use std::str::FromStr;
impl FromStr for Version {
type Err = crate::ProcErr;
fn from_str(s: &str) -> Result<Version, crate::ProcErr> {
if let Some(p1) = s[14..].find('(') {
let p1 = 14 + p1;
if let Some(p2) = s[p1+1..].find('@') {
let p2 = p2 + p1 + 1;
if let Some(p3) = s[p2 + 1..].find(')') {
let p3 = p2 + p3 + 1;
if let Some(p4) = s[p3+3..].rfind(')') {
let p4 = p3 + p4 + 3;
if let Some(p5) = s[p4+2..].find(' ') {
let p5 = p4 + p5 + 2;
if let Some(p6) = s[p5+1..].find(' '){
let p6 = p5 + p6 + 1;
let uts_release = s[14..p1-1].to_string();
let linux_compiler_by = s[p1+1..p2].to_string();
let linux_compiler_host = s[p2+1..p3].to_string();
let linux_compiler = s[p3+3..p4].to_string();
let uts_version = s[p4+3..p5].to_string();
let config_flag = s[p5+1..p6].to_string();
let timestamp = s[p6+1..].to_string();
return Ok(Version{
uts_release, linux_compiler_by, linux_compiler_host,
linux_compiler, uts_version, config_flag, timestamp
})
}
}
}
}
}
}
Err("unknow format".into())
}
}
instance_impl! {
version, "/proc/version", Version
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_parse_version() {
let source = "Linux version 3.10.0-1062.1.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Fri Sep 13 22:55:44 UTC 2019";
let correct = Version{
uts_release: String::from("3.10.0-1062.1.1.el7.x86_64"),
linux_compiler_by: String::from("mockbuild"),
linux_compiler_host: String::from("kbuilder.bsys.centos.org"),
linux_compiler: String::from("gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) "),
uts_version: String::from("1"),
config_flag: String::from("SMP"),
timestamp: String::from("Fri Sep 13 22:55:44 UTC 2019")
};
assert_eq!(correct, source.parse::<Version>().unwrap())
}
}