~danyspin97/initrz

bc9c9308a9781511f758bf8518cd5d04a0e7eb59 — Danilo Spinella 4 months ago 909859e
Remove common library and move code to module_loader module
8 files changed, 111 insertions(+), 167 deletions(-)

M Cargo.lock
M Cargo.toml
D src/common/Cargo.toml
D src/common/src/lib.rs
D src/common/src/modules.rs
M src/initrz/Cargo.toml
M src/initrz/src/module_loader.rs
M src/mkinitrz/Cargo.toml
M Cargo.lock => Cargo.lock +0 -11
@@ 238,15 238,6 @@ dependencies = [
]

[[package]]
name = "common"
version = "0.1.0"
dependencies = [
 "anyhow",
 "log",
 "rayon",
]

[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 411,7 402,6 @@ version = "0.1.0"
dependencies = [
 "anyhow",
 "bstr",
 "common",
 "dowser",
 "either",
 "glob",


@@ 569,7 559,6 @@ version = "0.1.0"
dependencies = [
 "anyhow",
 "clap 3.0.0-beta.2",
 "common",
 "dowser",
 "libc",
 "log",

M Cargo.toml => Cargo.toml +0 -1
@@ 1,7 1,6 @@
[workspace]

members = [
    "src/common",
    "src/initrz",
    "src/mkinitrz",
]

D src/common/Cargo.toml => src/common/Cargo.toml +0 -12
@@ 1,12 0,0 @@
[package]
name = "common"
version = "0.1.0"
authors = ["Danilo Spinella <oss@danyspin97.org>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
log = "0.4"
rayon = "1.5"


D src/common/src/lib.rs => src/common/src/lib.rs +0 -3
@@ 1,3 0,0 @@
mod modules;

pub use modules::Modules;

D src/common/src/modules.rs => src/common/src/modules.rs +0 -134
@@ 1,134 0,0 @@
use std::{
    collections::HashMap,
    fs::File,
    io::{BufRead, BufReader},
    path::Path,
};

use anyhow::{bail, Context, Result};
use log::warn;

pub struct Module {
    pub filename: String,
    pub deps: Vec<String>,
}

pub struct Modules {
    data: HashMap<String, Module>,
}

impl Modules {
    pub fn new(kernel_root: &Path) -> Result<Modules> {
        Ok(Modules {
            data: parse_module_dep(&kernel_root.join("modules.dep"))?,
        })
    }

    pub fn get(&self, module: &str) -> Option<&Module> {
        self.data.get(module)
    }
}

pub fn parse_module_dep(filename: &Path) -> Result<HashMap<String, Module>> {
    let file =
        File::open(filename).with_context(|| format!("unable to open filename {:?}", filename))?;
    let lines = BufReader::new(file).lines();
    Ok(lines
        .filter_map(|line: Result<String, _>| line.ok())
        .map(|line| -> Result<(String, Module)> {
            let token_index = line
                .find(':')
                .with_context(|| format!("could not find ':' in line:\n{}", line))?;
            let module_filename = &line[0..token_index];
            let module = if let Ok(module) = get_module_name(module_filename) {
                module
            } else {
                bail!("{} is not a valid module name", module_filename);
            };
            let mut deps: Vec<String> = Vec::new();
            let rest_of_line = &line[token_index + 1..];
            if rest_of_line.len() != 0 {
                // iter.rest() returns " kernel/..." so skip the first space
                let split = rest_of_line[1..].split(' ');
                split
                    .filter_map(|dep| get_module_name(dep).ok())
                    .for_each(|dep| deps.push(dep));

                deps.reverse();
            }
            Ok((
                module,
                Module {
                    filename: module_filename.to_string(),
                    deps,
                },
            ))
        })
        .filter_map(|res| res.ok())
        .collect())
}

fn get_module_name(filename: &str) -> Result<String> {
    Ok(Path::new(filename)
        .file_stem()
        .and_then(|module| std::path::Path::new(module).file_stem())
        .with_context(|| format!("failed to get module name of file {}", filename))?
        .to_str()
        .with_context(|| {
            format!(
                "failed to convert the module name in file {} from OsStr to Str",
                filename
            )
        })?
        .to_string())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_module_dep_test() {
        let filename = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/test/module.dep"));
        let map = parse_module_dep(filename).unwrap();

        let mut expected_map = HashMap::new();

        let mut mhi_deps: Vec<String> = Vec::new();
        mhi_deps.push("mhi".to_string());
        mhi_deps.push("ns".to_string());
        mhi_deps.push("qrtr".to_string());
        expected_map.insert(
            "qrtr-mhi".to_string(),
            Module {
                filename: String::from("kernel/net/qrtr/qrtr-mhi.ko.xz"),
                deps: mhi_deps,
            },
        );

        let mut nvidia_uvm_deps: Vec<String> = Vec::new();
        nvidia_uvm_deps.push("nvidia".to_string());
        expected_map.insert(
            "nvidia-uvm".to_string(),
            Module {
                filename: String::from("kernel/drivers/video/nvidia-uvm.ko.xz"),
                deps: nvidia_uvm_deps,
            },
        );

        expected_map.insert(
            "nvidia".to_string(),
            Module {
                filename: String::from("kernel/drivers/video/nvidia.ko.xz"),
                deps: Vec::new(),
            },
        );

        assert_eq!(map.len(), 3);
        for (module_name, module) in map {
            let expected_module = expected_map.get(&module_name).expect("no module found");
            assert_eq!(module.filename, expected_module.filename);
            assert_eq!(module.deps, expected_module.deps);
        }
    }
}

M src/initrz/Cargo.toml => src/initrz/Cargo.toml +0 -1
@@ 6,7 6,6 @@ edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
common = { path = "../common" }
anyhow = "1.0"
bstr = "0.2"
dowser = "0.2"

M src/initrz/src/module_loader.rs => src/initrz/src/module_loader.rs +111 -4
@@ 15,20 15,77 @@ use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::sync::RwLock;

use common::Modules;

pub struct ModAlias {
    pattern: Pattern,
    module: String,
}

pub struct Module {
    pub filename: String,
    pub deps: Vec<String>,
}

pub struct ModuleLoader {
    modules: Modules,
    modules: HashMap<String, Module>,
    aliases: Vec<ModAlias>,
    modules_loaded: RwLock<HashSet<String>>,
    kernel_root: PathBuf,
}

pub fn parse_module_dep(filename: &Path) -> Result<HashMap<String, Module>> {
    let file =
        File::open(filename).with_context(|| format!("unable to open filename {:?}", filename))?;
    let lines = BufReader::new(file).lines();
    Ok(lines
        .filter_map(|line: Result<String, _>| line.ok())
        .map(|line| -> Result<(String, Module)> {
            let token_index = line
                .find(':')
                .with_context(|| format!("could not find ':' in line:\n{}", line))?;
            let module_filename = &line[0..token_index];
            let module = if let Ok(module) = get_module_name(module_filename) {
                module
            } else {
                bail!("{} is not a valid module name", module_filename);
            };
            let mut deps: Vec<String> = Vec::new();
            let rest_of_line = &line[token_index + 1..];
            if rest_of_line.len() != 0 {
                // iter.rest() returns " kernel/..." so skip the first space
                let split = rest_of_line[1..].split(' ');
                split
                    .filter_map(|dep| get_module_name(dep).ok())
                    .for_each(|dep| deps.push(dep));

                deps.reverse();
            }
            Ok((
                module,
                Module {
                    filename: module_filename.to_string(),
                    deps,
                },
            ))
        })
        .filter_map(|res| res.ok())
        .collect())
}

fn get_module_name(filename: &str) -> Result<String> {
    Ok(Path::new(filename)
        .file_stem()
        .and_then(|module| std::path::Path::new(module).file_stem())
        .with_context(|| format!("failed to get module name of file {}", filename))?
        .to_str()
        .with_context(|| {
            format!(
                "failed to convert the module name in file {} from OsStr to Str",
                filename
            )
        })?
        .to_string())
}

pub fn parse_module_alias(filename: &Path) -> Result<Vec<ModAlias>> {
    let file =
        File::open(filename).with_context(|| format!("unable to open file {:?}", filename))?;


@@ 62,7 119,7 @@ impl ModuleLoader {

        modules.reserve(glob(&kernel_root.join("*.ko.xz").as_os_str().to_string_lossy())?.count());
        Ok(ModuleLoader {
            modules: Modules::new(&kernel_root)?,
            modules: parse_module_dep(&kernel_root.join("modules.dep"))?,
            aliases: parse_module_alias(&kernel_root.join("modules.alias"))?,
            modules_loaded: RwLock::new(modules),
            kernel_root,


@@ 113,3 170,53 @@ impl ModuleLoader {
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_module_dep_test() {
        let filename = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/test/module.dep"));
        let map = parse_module_dep(filename).unwrap();

        let mut expected_map = HashMap::new();

        let mut mhi_deps: Vec<String> = Vec::new();
        mhi_deps.push("mhi".to_string());
        mhi_deps.push("ns".to_string());
        mhi_deps.push("qrtr".to_string());
        expected_map.insert(
            "qrtr-mhi".to_string(),
            Module {
                filename: String::from("kernel/net/qrtr/qrtr-mhi.ko.xz"),
                deps: mhi_deps,
            },
        );

        let mut nvidia_uvm_deps: Vec<String> = Vec::new();
        nvidia_uvm_deps.push("nvidia".to_string());
        expected_map.insert(
            "nvidia-uvm".to_string(),
            Module {
                filename: String::from("kernel/drivers/video/nvidia-uvm.ko.xz"),
                deps: nvidia_uvm_deps,
            },
        );

        expected_map.insert(
            "nvidia".to_string(),
            Module {
                filename: String::from("kernel/drivers/video/nvidia.ko.xz"),
                deps: Vec::new(),
            },
        );

        assert_eq!(map.len(), 3);
        for (module_name, module) in map {
            let expected_module = expected_map.get(&module_name).expect("no module found");
            assert_eq!(module.filename, expected_module.filename);
            assert_eq!(module.deps, expected_module.deps);
        }
    }
}

M src/mkinitrz/Cargo.toml => src/mkinitrz/Cargo.toml +0 -1
@@ 7,7 7,6 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
common = { path = "../common" }
anyhow = "1.0"
clap = { git = "https://github.com/clap-rs/clap/" }
dowser = "0.2"