isr_dl_linux/
banner.rs

1use std::sync::LazyLock;
2
3use regex::Regex;
4
5#[derive(Debug)]
6pub enum LinuxVersionSignature {
7    Ubuntu(UbuntuVersionSignature),
8}
9
10#[derive(Debug)]
11pub struct UbuntuVersionSignature {
12    pub release: String,
13    pub revision: String,
14    pub kernel_flavour: String,
15    pub mainline_kernel_version: String,
16}
17
18/// Linux banner.
19#[derive(Debug)]
20pub struct LinuxBanner {
21    pub uts_release: String,
22    pub linux_compile_by: String,
23    pub linux_compile_host: String,
24    pub linux_compiler: String,
25    pub uts_version: String,
26    pub version_signature: Option<LinuxVersionSignature>,
27}
28
29// root/debian/rules.d/2-binary-arch.mk (ubuntu CONFIG_VERSION_SIGNATURE)
30
31impl LinuxBanner {
32    pub fn parse(banner: &str) -> Option<Self> {
33        //
34        // Linux version 6.8.0-40-generic
35        // (buildd@lcy02-amd64-078)
36        // (x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38)
37        // #40~22.04.3-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 30 17:30:19 UTC 2 (Ubuntu 6.8.0-40.40~22.04.3-generic 6.8.12)
38        //
39
40        static LINUX_VERSION_REGEX: LazyLock<Regex> = LazyLock::new(|| {
41            Regex::new(concat!(
42                r"Linux version (?<UTS_RELEASE>[0-9]+\.[0-9]+\.[0-9]+[^ ]*) ",
43                r"\((?<LINUX_COMPILE_BY>[^@]*)@(?<LINUX_COMPILE_HOST>[^)]*)\) ",
44                r"\((?<LINUX_COMPILER>.*)\) ",
45                r"#(?<UTS_VERSION>.*)"
46            ))
47            .unwrap()
48        });
49
50        let captures = LINUX_VERSION_REGEX.captures(banner)?;
51        let version_signature = try_parse_ubuntu_signature(&captures["UTS_VERSION"]);
52
53        Some(Self {
54            uts_release: captures["UTS_RELEASE"].to_string(),
55            linux_compile_by: captures["LINUX_COMPILE_BY"].to_string(),
56            linux_compile_host: captures["LINUX_COMPILE_HOST"].to_string(),
57            linux_compiler: captures["LINUX_COMPILER"].to_string(),
58            uts_version: captures["UTS_VERSION"].to_string(),
59            version_signature,
60        })
61    }
62}
63
64fn try_parse_ubuntu_signature(uts_version: &str) -> Option<LinuxVersionSignature> {
65    //
66    // (Ubuntu 6.8.0-40.40~22.04.3-generic 6.8.12)
67    //
68
69    static UBUNTU_VERSION_REGEX: LazyLock<Regex> = LazyLock::new(|| {
70        Regex::new(concat!(
71            r"\(Ubuntu ",
72            r"(?<UBUNTU_RELEASE>.*)-(?<UBUNTU_REVISION>.*)-(?<UBUNTU_KERNEL_FLAVOUR>.*) ",
73            r"(?<UBUNTU_MAINLINE_KERNEL_VERSION>.*)\)"
74        ))
75        .unwrap()
76    });
77
78    let captures = UBUNTU_VERSION_REGEX.captures(uts_version)?;
79
80    Some(LinuxVersionSignature::Ubuntu(UbuntuVersionSignature {
81        release: captures["UBUNTU_RELEASE"].into(),
82        revision: captures["UBUNTU_REVISION"].into(),
83        kernel_flavour: captures["UBUNTU_KERNEL_FLAVOUR"].into(),
84        mainline_kernel_version: captures["UBUNTU_MAINLINE_KERNEL_VERSION"].into(),
85    }))
86}