kanit

Toy init system
Log | Files | Refs | README | LICENSE

modules.rs (2154B)


      1 use std::os::unix::ffi::OsStrExt;
      2 
      3 use async_process::Command;
      4 use async_trait::async_trait;
      5 use blocking::unblock;
      6 use futures_lite::StreamExt;
      7 use futures_lite::stream::iter;
      8 use log::{info, warn};
      9 use walkdir::WalkDir;
     10 
     11 use kanit_common::error::{Context, Result};
     12 use kanit_unit::Unit;
     13 
     14 use crate::unit_name;
     15 
     16 pub struct Modules;
     17 
     18 const LOADED_FOLDERS: [&str; 3] = [
     19     "/etc/modules-load.d/",
     20     "/run/modules-load./",
     21     "/usr/lib/modules-load.d/",
     22 ];
     23 
     24 #[async_trait]
     25 impl Unit for Modules {
     26     unit_name!("modules");
     27 
     28     async fn start(&mut self) -> Result<()> {
     29         if async_fs::metadata("/proc/modules").await.is_err() {
     30             return Ok(());
     31         }
     32 
     33         for dir in LOADED_FOLDERS.iter() {
     34             let modules = iter(
     35                 unblock(move || {
     36                     WalkDir::new(dir)
     37                         .into_iter()
     38                         .filter_map(|e| e.ok())
     39                         .filter(|e| {
     40                             e.file_type().is_file() && e.file_name().as_bytes().ends_with(b".conf")
     41                         })
     42                 })
     43                 .await,
     44             )
     45             .then(|e| async { async_fs::read_to_string(e.into_path()).await })
     46             .filter_map(|e| e.ok())
     47             .collect::<Vec<String>>()
     48             .await
     49             .into_iter()
     50             .flat_map(|e| {
     51                 e.lines()
     52                     .filter(|l| !l.starts_with('#') && !l.starts_with(';') && !l.is_empty())
     53                     .map(|s| s.to_string())
     54                     .collect::<Vec<String>>()
     55             });
     56 
     57             for module in modules {
     58                 info!("loading module {module}");
     59 
     60                 let succ = Command::new("modprobe")
     61                     .args(["-b", "-a", "-v", &module])
     62                     .spawn()
     63                     .context("failed to spawn modprobe")?
     64                     .status()
     65                     .await
     66                     .context("failed to wait")?
     67                     .success();
     68 
     69                 if !succ {
     70                     warn!("failed to load module {module}");
     71                 }
     72             }
     73         }
     74 
     75         Ok(())
     76     }
     77 }