1*f9fe30beSLoGin use core::{ 2*f9fe30beSLoGin str, 3*f9fe30beSLoGin sync::atomic::{fence, Ordering}, 4*f9fe30beSLoGin }; 5*f9fe30beSLoGin 6*f9fe30beSLoGin use alloc::{ffi::CString, vec::Vec}; 7*f9fe30beSLoGin 8*f9fe30beSLoGin use crate::libs::spinlock::SpinLock; 9*f9fe30beSLoGin 10*f9fe30beSLoGin use super::boot_params; 11*f9fe30beSLoGin 12*f9fe30beSLoGin #[::linkme::distributed_slice] 13*f9fe30beSLoGin pub static KCMDLINE_PARAM_EARLY_KV: [KernelCmdlineParameter] = [..]; 14*f9fe30beSLoGin 15*f9fe30beSLoGin #[::linkme::distributed_slice] 16*f9fe30beSLoGin pub static KCMDLINE_PARAM_KV: [KernelCmdlineParameter] = [..]; 17*f9fe30beSLoGin 18*f9fe30beSLoGin #[::linkme::distributed_slice] 19*f9fe30beSLoGin pub static KCMDLINE_PARAM_ARG: [KernelCmdlineParameter] = [..]; 20*f9fe30beSLoGin 21*f9fe30beSLoGin static KERNEL_CMDLINE_PARAM_MANAGER: KernelCmdlineManager = KernelCmdlineManager::new(); 22*f9fe30beSLoGin 23*f9fe30beSLoGin #[inline(always)] 24*f9fe30beSLoGin pub fn kenrel_cmdline_param_manager() -> &'static KernelCmdlineManager { 25*f9fe30beSLoGin &KERNEL_CMDLINE_PARAM_MANAGER 26*f9fe30beSLoGin } 27*f9fe30beSLoGin 28*f9fe30beSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)] 29*f9fe30beSLoGin pub enum KCmdlineParamType { 30*f9fe30beSLoGin /// bool类型参数 31*f9fe30beSLoGin Arg, 32*f9fe30beSLoGin /// key-value类型参数 33*f9fe30beSLoGin KV, 34*f9fe30beSLoGin /// 内存管理初始化之前的KV参数 35*f9fe30beSLoGin EarlyKV, 36*f9fe30beSLoGin } 37*f9fe30beSLoGin 38*f9fe30beSLoGin pub struct KernelCmdlineParamBuilder { 39*f9fe30beSLoGin name: &'static str, 40*f9fe30beSLoGin ty: KCmdlineParamType, 41*f9fe30beSLoGin default_str: &'static str, 42*f9fe30beSLoGin default_bool: bool, 43*f9fe30beSLoGin inv: bool, 44*f9fe30beSLoGin } 45*f9fe30beSLoGin 46*f9fe30beSLoGin impl KernelCmdlineParamBuilder { 47*f9fe30beSLoGin pub const fn new(name: &'static str, ty: KCmdlineParamType) -> Self { 48*f9fe30beSLoGin Self { 49*f9fe30beSLoGin name, 50*f9fe30beSLoGin ty, 51*f9fe30beSLoGin default_str: "", 52*f9fe30beSLoGin default_bool: false, 53*f9fe30beSLoGin inv: false, 54*f9fe30beSLoGin } 55*f9fe30beSLoGin } 56*f9fe30beSLoGin 57*f9fe30beSLoGin pub const fn default_str(mut self, default_str: &'static str) -> Self { 58*f9fe30beSLoGin self.default_str = default_str; 59*f9fe30beSLoGin self 60*f9fe30beSLoGin } 61*f9fe30beSLoGin 62*f9fe30beSLoGin pub const fn default_bool(mut self, default_bool: bool) -> Self { 63*f9fe30beSLoGin self.default_bool = default_bool; 64*f9fe30beSLoGin self 65*f9fe30beSLoGin } 66*f9fe30beSLoGin 67*f9fe30beSLoGin pub const fn inv(mut self, inv: bool) -> Self { 68*f9fe30beSLoGin self.inv = inv; 69*f9fe30beSLoGin self 70*f9fe30beSLoGin } 71*f9fe30beSLoGin 72*f9fe30beSLoGin pub const fn build_early_kv(self) -> Option<KernelCmdlineEarlyKV> { 73*f9fe30beSLoGin if matches!(self.ty, KCmdlineParamType::EarlyKV) { 74*f9fe30beSLoGin Some(KernelCmdlineEarlyKV { 75*f9fe30beSLoGin name: self.name, 76*f9fe30beSLoGin value: [0; KernelCmdlineEarlyKV::VALUE_MAX_LEN], 77*f9fe30beSLoGin index: 0, 78*f9fe30beSLoGin initialized: false, 79*f9fe30beSLoGin default: self.default_str, 80*f9fe30beSLoGin }) 81*f9fe30beSLoGin } else { 82*f9fe30beSLoGin None 83*f9fe30beSLoGin } 84*f9fe30beSLoGin } 85*f9fe30beSLoGin 86*f9fe30beSLoGin pub const fn build(self) -> Option<KernelCmdlineParameter> { 87*f9fe30beSLoGin match self.ty { 88*f9fe30beSLoGin KCmdlineParamType::Arg => Some(KernelCmdlineParameter::Arg(KernelCmdlineArg { 89*f9fe30beSLoGin name: self.name, 90*f9fe30beSLoGin value: self.default_bool, 91*f9fe30beSLoGin initialized: false, 92*f9fe30beSLoGin inv: self.inv, 93*f9fe30beSLoGin default: self.default_bool, 94*f9fe30beSLoGin })), 95*f9fe30beSLoGin KCmdlineParamType::KV => Some(KernelCmdlineParameter::KV(KernelCmdlineKV { 96*f9fe30beSLoGin name: self.name, 97*f9fe30beSLoGin value: None, 98*f9fe30beSLoGin initialized: false, 99*f9fe30beSLoGin default: self.default_str, 100*f9fe30beSLoGin })), 101*f9fe30beSLoGin _ => None, 102*f9fe30beSLoGin } 103*f9fe30beSLoGin } 104*f9fe30beSLoGin } 105*f9fe30beSLoGin 106*f9fe30beSLoGin #[allow(dead_code)] 107*f9fe30beSLoGin pub enum KernelCmdlineParameter { 108*f9fe30beSLoGin Arg(KernelCmdlineArg), 109*f9fe30beSLoGin KV(KernelCmdlineKV), 110*f9fe30beSLoGin EarlyKV(&'static KernelCmdlineEarlyKV), 111*f9fe30beSLoGin } 112*f9fe30beSLoGin 113*f9fe30beSLoGin impl KernelCmdlineParameter { 114*f9fe30beSLoGin pub fn name(&self) -> &str { 115*f9fe30beSLoGin match self { 116*f9fe30beSLoGin KernelCmdlineParameter::Arg(v) => v.name, 117*f9fe30beSLoGin KernelCmdlineParameter::KV(v) => v.name, 118*f9fe30beSLoGin KernelCmdlineParameter::EarlyKV(v) => v.name, 119*f9fe30beSLoGin } 120*f9fe30beSLoGin } 121*f9fe30beSLoGin 122*f9fe30beSLoGin /// 获取bool类型参数的值 123*f9fe30beSLoGin pub fn value_bool(&self) -> Option<bool> { 124*f9fe30beSLoGin match self { 125*f9fe30beSLoGin KernelCmdlineParameter::Arg(v) => Some(v.value()), 126*f9fe30beSLoGin _ => None, 127*f9fe30beSLoGin } 128*f9fe30beSLoGin } 129*f9fe30beSLoGin 130*f9fe30beSLoGin /// 获取key-value类型参数的值 131*f9fe30beSLoGin pub fn value_str(&self) -> Option<&str> { 132*f9fe30beSLoGin match self { 133*f9fe30beSLoGin KernelCmdlineParameter::Arg(_) => None, 134*f9fe30beSLoGin KernelCmdlineParameter::KV(v) => v 135*f9fe30beSLoGin .value 136*f9fe30beSLoGin .as_ref() 137*f9fe30beSLoGin .and_then(|v| str::from_utf8(v.as_bytes()).ok()), 138*f9fe30beSLoGin KernelCmdlineParameter::EarlyKV(v) => v.value_str(), 139*f9fe30beSLoGin } 140*f9fe30beSLoGin } 141*f9fe30beSLoGin 142*f9fe30beSLoGin pub fn is_arg(&self) -> bool { 143*f9fe30beSLoGin matches!(self, KernelCmdlineParameter::Arg(_)) 144*f9fe30beSLoGin } 145*f9fe30beSLoGin 146*f9fe30beSLoGin pub fn is_kv(&self) -> bool { 147*f9fe30beSLoGin matches!(self, KernelCmdlineParameter::KV(_)) 148*f9fe30beSLoGin } 149*f9fe30beSLoGin 150*f9fe30beSLoGin pub fn is_early_kv(&self) -> bool { 151*f9fe30beSLoGin matches!(self, KernelCmdlineParameter::EarlyKV(_)) 152*f9fe30beSLoGin } 153*f9fe30beSLoGin 154*f9fe30beSLoGin /// 强行获取可变引用 155*f9fe30beSLoGin /// 156*f9fe30beSLoGin /// # Safety 157*f9fe30beSLoGin /// 158*f9fe30beSLoGin /// 只能在内核初始化阶段pid0使用! 159*f9fe30beSLoGin #[allow(clippy::mut_from_ref)] 160*f9fe30beSLoGin unsafe fn force_mut(&self) -> &mut Self { 161*f9fe30beSLoGin let p = self as *const Self as *mut Self; 162*f9fe30beSLoGin p.as_mut().unwrap() 163*f9fe30beSLoGin } 164*f9fe30beSLoGin } 165*f9fe30beSLoGin 166*f9fe30beSLoGin #[derive(Debug)] 167*f9fe30beSLoGin pub struct KernelCmdlineArg { 168*f9fe30beSLoGin name: &'static str, 169*f9fe30beSLoGin value: bool, 170*f9fe30beSLoGin initialized: bool, 171*f9fe30beSLoGin /// 是否反转 172*f9fe30beSLoGin inv: bool, 173*f9fe30beSLoGin default: bool, 174*f9fe30beSLoGin } 175*f9fe30beSLoGin 176*f9fe30beSLoGin impl KernelCmdlineArg { 177*f9fe30beSLoGin pub fn value(&self) -> bool { 178*f9fe30beSLoGin volatile_read!(self.value) 179*f9fe30beSLoGin } 180*f9fe30beSLoGin } 181*f9fe30beSLoGin 182*f9fe30beSLoGin pub struct KernelCmdlineKV { 183*f9fe30beSLoGin name: &'static str, 184*f9fe30beSLoGin value: Option<CString>, 185*f9fe30beSLoGin initialized: bool, 186*f9fe30beSLoGin default: &'static str, 187*f9fe30beSLoGin } 188*f9fe30beSLoGin 189*f9fe30beSLoGin /// 在内存管理初始化之前的KV参数 190*f9fe30beSLoGin pub struct KernelCmdlineEarlyKV { 191*f9fe30beSLoGin name: &'static str, 192*f9fe30beSLoGin value: [u8; Self::VALUE_MAX_LEN], 193*f9fe30beSLoGin index: usize, 194*f9fe30beSLoGin initialized: bool, 195*f9fe30beSLoGin default: &'static str, 196*f9fe30beSLoGin } 197*f9fe30beSLoGin 198*f9fe30beSLoGin impl KernelCmdlineEarlyKV { 199*f9fe30beSLoGin pub const VALUE_MAX_LEN: usize = 256; 200*f9fe30beSLoGin 201*f9fe30beSLoGin pub fn value(&self) -> &[u8] { 202*f9fe30beSLoGin &self.value[..self.index] 203*f9fe30beSLoGin } 204*f9fe30beSLoGin 205*f9fe30beSLoGin pub fn value_str(&self) -> Option<&str> { 206*f9fe30beSLoGin core::str::from_utf8(&self.value[..self.index]).ok() 207*f9fe30beSLoGin } 208*f9fe30beSLoGin 209*f9fe30beSLoGin /// 强行获取可变引用 210*f9fe30beSLoGin /// 211*f9fe30beSLoGin /// # Safety 212*f9fe30beSLoGin /// 213*f9fe30beSLoGin /// 只能在内核初始化阶段pid0使用! 214*f9fe30beSLoGin #[allow(clippy::mut_from_ref)] 215*f9fe30beSLoGin unsafe fn force_mut(&self) -> &mut Self { 216*f9fe30beSLoGin let p = self as *const Self as *mut Self; 217*f9fe30beSLoGin p.as_mut().unwrap() 218*f9fe30beSLoGin } 219*f9fe30beSLoGin } 220*f9fe30beSLoGin 221*f9fe30beSLoGin pub struct KernelCmdlineManager { 222*f9fe30beSLoGin inner: SpinLock<InnerKernelCmdlineManager>, 223*f9fe30beSLoGin } 224*f9fe30beSLoGin 225*f9fe30beSLoGin pub(super) struct InnerKernelCmdlineManager { 226*f9fe30beSLoGin /// init进程的路径 227*f9fe30beSLoGin init_path: Option<CString>, 228*f9fe30beSLoGin init_args: Vec<CString>, 229*f9fe30beSLoGin init_envs: Vec<CString>, 230*f9fe30beSLoGin } 231*f9fe30beSLoGin 232*f9fe30beSLoGin impl KernelCmdlineManager { 233*f9fe30beSLoGin const fn new() -> Self { 234*f9fe30beSLoGin Self { 235*f9fe30beSLoGin inner: SpinLock::new(InnerKernelCmdlineManager { 236*f9fe30beSLoGin init_path: None, 237*f9fe30beSLoGin init_args: Vec::new(), 238*f9fe30beSLoGin init_envs: Vec::new(), 239*f9fe30beSLoGin }), 240*f9fe30beSLoGin } 241*f9fe30beSLoGin } 242*f9fe30beSLoGin 243*f9fe30beSLoGin pub(super) fn init_proc_path(&self) -> Option<CString> { 244*f9fe30beSLoGin self.inner.lock().init_path.clone() 245*f9fe30beSLoGin } 246*f9fe30beSLoGin 247*f9fe30beSLoGin pub(super) fn init_proc_args(&self) -> Vec<CString> { 248*f9fe30beSLoGin self.inner.lock().init_args.clone() 249*f9fe30beSLoGin } 250*f9fe30beSLoGin 251*f9fe30beSLoGin pub(super) fn init_proc_envs(&self) -> Vec<CString> { 252*f9fe30beSLoGin self.inner.lock().init_envs.clone() 253*f9fe30beSLoGin } 254*f9fe30beSLoGin 255*f9fe30beSLoGin /// 在内存管理初始化之前设置部分参数 256*f9fe30beSLoGin pub fn early_init(&self) { 257*f9fe30beSLoGin let boot_params = boot_params().read(); 258*f9fe30beSLoGin 259*f9fe30beSLoGin for argument in self.split_args(boot_params.boot_cmdline_str()) { 260*f9fe30beSLoGin let (node, option, value) = match self.split_arg(argument) { 261*f9fe30beSLoGin Some(v) => v, 262*f9fe30beSLoGin None => continue, 263*f9fe30beSLoGin }; 264*f9fe30beSLoGin // 查找参数 265*f9fe30beSLoGin if let Some(param) = self.find_param(node, option, KCmdlineParamType::EarlyKV) { 266*f9fe30beSLoGin let param = unsafe { param.force_mut() }; 267*f9fe30beSLoGin match param { 268*f9fe30beSLoGin KernelCmdlineParameter::EarlyKV(p) => { 269*f9fe30beSLoGin let p = unsafe { p.force_mut() }; 270*f9fe30beSLoGin if let Some(value) = value { 271*f9fe30beSLoGin let value = value.as_bytes(); 272*f9fe30beSLoGin let len = value.len().min(KernelCmdlineEarlyKV::VALUE_MAX_LEN); 273*f9fe30beSLoGin p.value[..len].copy_from_slice(&value[..len]); 274*f9fe30beSLoGin p.index = len; 275*f9fe30beSLoGin } 276*f9fe30beSLoGin p.initialized = true; 277*f9fe30beSLoGin } 278*f9fe30beSLoGin _ => unreachable!(), 279*f9fe30beSLoGin } 280*f9fe30beSLoGin fence(Ordering::SeqCst); 281*f9fe30beSLoGin } 282*f9fe30beSLoGin } 283*f9fe30beSLoGin 284*f9fe30beSLoGin // 初始化默认值 285*f9fe30beSLoGin KCMDLINE_PARAM_EARLY_KV.iter().for_each(|x| { 286*f9fe30beSLoGin let x = unsafe { x.force_mut() }; 287*f9fe30beSLoGin if let KernelCmdlineParameter::EarlyKV(v) = x { 288*f9fe30beSLoGin if !v.initialized { 289*f9fe30beSLoGin let v = unsafe { v.force_mut() }; 290*f9fe30beSLoGin let len = v.default.len().min(KernelCmdlineEarlyKV::VALUE_MAX_LEN); 291*f9fe30beSLoGin v.value[..len].copy_from_slice(v.default.as_bytes()); 292*f9fe30beSLoGin v.index = len; 293*f9fe30beSLoGin v.initialized = true; 294*f9fe30beSLoGin } 295*f9fe30beSLoGin } 296*f9fe30beSLoGin }); 297*f9fe30beSLoGin } 298*f9fe30beSLoGin 299*f9fe30beSLoGin /// 在内存管理初始化之后设置命令行参数 300*f9fe30beSLoGin pub fn init(&self) { 301*f9fe30beSLoGin let mut inner = self.inner.lock(); 302*f9fe30beSLoGin let boot_params = boot_params().read(); 303*f9fe30beSLoGin // `--`以后的参数都是init进程的参数 304*f9fe30beSLoGin let mut kernel_cmdline_end = false; 305*f9fe30beSLoGin for argument in self.split_args(boot_params.boot_cmdline_str()) { 306*f9fe30beSLoGin if kernel_cmdline_end { 307*f9fe30beSLoGin if inner.init_path.is_none() { 308*f9fe30beSLoGin panic!("cmdline: init proc path is not set while init proc args are set"); 309*f9fe30beSLoGin } 310*f9fe30beSLoGin if !argument.is_empty() { 311*f9fe30beSLoGin inner.init_args.push(CString::new(argument).unwrap()); 312*f9fe30beSLoGin } 313*f9fe30beSLoGin continue; 314*f9fe30beSLoGin } 315*f9fe30beSLoGin 316*f9fe30beSLoGin if argument == "--" { 317*f9fe30beSLoGin kernel_cmdline_end = true; 318*f9fe30beSLoGin continue; 319*f9fe30beSLoGin } 320*f9fe30beSLoGin 321*f9fe30beSLoGin let (node, option, value) = match self.split_arg(argument) { 322*f9fe30beSLoGin Some(v) => v, 323*f9fe30beSLoGin None => continue, 324*f9fe30beSLoGin }; 325*f9fe30beSLoGin if option == "init" && value.is_some() { 326*f9fe30beSLoGin if inner.init_path.is_some() { 327*f9fe30beSLoGin panic!("cmdline: init proc path is set twice"); 328*f9fe30beSLoGin } 329*f9fe30beSLoGin inner.init_path = Some(CString::new(value.unwrap()).unwrap()); 330*f9fe30beSLoGin continue; 331*f9fe30beSLoGin } 332*f9fe30beSLoGin // log::debug!( 333*f9fe30beSLoGin // "cmdline: node: {:?}, option: {:?}, value: {:?}", 334*f9fe30beSLoGin // node, 335*f9fe30beSLoGin // option, 336*f9fe30beSLoGin // value 337*f9fe30beSLoGin // ); 338*f9fe30beSLoGin if let Some(param) = self.find_param(node, option, KCmdlineParamType::KV) { 339*f9fe30beSLoGin let param = unsafe { param.force_mut() }; 340*f9fe30beSLoGin match param { 341*f9fe30beSLoGin KernelCmdlineParameter::KV(p) => { 342*f9fe30beSLoGin if p.value.is_some() { 343*f9fe30beSLoGin log::warn!("cmdline: parameter {} is set twice", p.name); 344*f9fe30beSLoGin continue; 345*f9fe30beSLoGin } 346*f9fe30beSLoGin p.value = Some(CString::new(value.unwrap()).unwrap()); 347*f9fe30beSLoGin p.initialized = true; 348*f9fe30beSLoGin } 349*f9fe30beSLoGin _ => unreachable!(), 350*f9fe30beSLoGin } 351*f9fe30beSLoGin fence(Ordering::SeqCst); 352*f9fe30beSLoGin } else if let Some(param) = self.find_param(node, option, KCmdlineParamType::Arg) { 353*f9fe30beSLoGin let param = unsafe { param.force_mut() }; 354*f9fe30beSLoGin match param { 355*f9fe30beSLoGin KernelCmdlineParameter::Arg(p) => { 356*f9fe30beSLoGin if p.initialized { 357*f9fe30beSLoGin log::warn!("cmdline: parameter {} is set twice", p.name); 358*f9fe30beSLoGin continue; 359*f9fe30beSLoGin } 360*f9fe30beSLoGin p.value = !p.inv; 361*f9fe30beSLoGin p.initialized = true; 362*f9fe30beSLoGin } 363*f9fe30beSLoGin _ => unreachable!(), 364*f9fe30beSLoGin } 365*f9fe30beSLoGin fence(Ordering::SeqCst); 366*f9fe30beSLoGin } else if node.is_none() { 367*f9fe30beSLoGin if let Some(val) = value { 368*f9fe30beSLoGin inner 369*f9fe30beSLoGin .init_envs 370*f9fe30beSLoGin .push(CString::new(format!("{}={}", option, val)).unwrap()); 371*f9fe30beSLoGin } else if !option.is_empty() { 372*f9fe30beSLoGin inner.init_args.push(CString::new(option).unwrap()); 373*f9fe30beSLoGin } 374*f9fe30beSLoGin } 375*f9fe30beSLoGin } 376*f9fe30beSLoGin fence(Ordering::SeqCst); 377*f9fe30beSLoGin // 初始化默认值 378*f9fe30beSLoGin self.default_initialize(); 379*f9fe30beSLoGin fence(Ordering::SeqCst); 380*f9fe30beSLoGin } 381*f9fe30beSLoGin 382*f9fe30beSLoGin fn default_initialize(&self) { 383*f9fe30beSLoGin KCMDLINE_PARAM_ARG.iter().for_each(|x| { 384*f9fe30beSLoGin let x = unsafe { x.force_mut() }; 385*f9fe30beSLoGin if let KernelCmdlineParameter::Arg(v) = x { 386*f9fe30beSLoGin if !v.initialized { 387*f9fe30beSLoGin v.value = v.default; 388*f9fe30beSLoGin v.initialized = true; 389*f9fe30beSLoGin } 390*f9fe30beSLoGin } 391*f9fe30beSLoGin fence(Ordering::SeqCst); 392*f9fe30beSLoGin }); 393*f9fe30beSLoGin 394*f9fe30beSLoGin KCMDLINE_PARAM_KV.iter().for_each(|x| { 395*f9fe30beSLoGin let x = unsafe { x.force_mut() }; 396*f9fe30beSLoGin if let KernelCmdlineParameter::KV(v) = x { 397*f9fe30beSLoGin if !v.initialized { 398*f9fe30beSLoGin v.value = Some(CString::new(v.default).unwrap()); 399*f9fe30beSLoGin v.initialized = true; 400*f9fe30beSLoGin } 401*f9fe30beSLoGin } 402*f9fe30beSLoGin fence(Ordering::SeqCst); 403*f9fe30beSLoGin }); 404*f9fe30beSLoGin } 405*f9fe30beSLoGin 406*f9fe30beSLoGin fn find_param( 407*f9fe30beSLoGin &self, 408*f9fe30beSLoGin node: Option<&str>, 409*f9fe30beSLoGin option: &str, 410*f9fe30beSLoGin param_typ: KCmdlineParamType, 411*f9fe30beSLoGin ) -> Option<&KernelCmdlineParameter> { 412*f9fe30beSLoGin let list = match param_typ { 413*f9fe30beSLoGin KCmdlineParamType::Arg => &KCMDLINE_PARAM_ARG, 414*f9fe30beSLoGin KCmdlineParamType::KV => &KCMDLINE_PARAM_KV, 415*f9fe30beSLoGin KCmdlineParamType::EarlyKV => &KCMDLINE_PARAM_EARLY_KV, 416*f9fe30beSLoGin }; 417*f9fe30beSLoGin 418*f9fe30beSLoGin list.iter().find(|x| { 419*f9fe30beSLoGin let name = x.name(); 420*f9fe30beSLoGin if let Some(node) = node { 421*f9fe30beSLoGin // 加1是因为有一个点号 422*f9fe30beSLoGin name.len() == (node.len() + option.len() + 1) 423*f9fe30beSLoGin && name.starts_with(node) 424*f9fe30beSLoGin && name[node.len() + 1..].starts_with(option) 425*f9fe30beSLoGin } else { 426*f9fe30beSLoGin name == option 427*f9fe30beSLoGin } 428*f9fe30beSLoGin }) 429*f9fe30beSLoGin } 430*f9fe30beSLoGin 431*f9fe30beSLoGin fn split_arg<'a>(&self, arg: &'a str) -> Option<(Option<&'a str>, &'a str, Option<&'a str>)> { 432*f9fe30beSLoGin let mut iter = arg.splitn(2, '='); 433*f9fe30beSLoGin let key = iter.next().unwrap(); 434*f9fe30beSLoGin let value = iter.next(); 435*f9fe30beSLoGin let value = value.map(|v| v.trim()); 436*f9fe30beSLoGin if value.is_some() && iter.next().is_some() { 437*f9fe30beSLoGin log::warn!("cmdline: invalid argument: {}", arg); 438*f9fe30beSLoGin return None; 439*f9fe30beSLoGin } 440*f9fe30beSLoGin 441*f9fe30beSLoGin let mut iter = key.splitn(2, '.'); 442*f9fe30beSLoGin let v1 = iter.next().map(|v| v.trim()); 443*f9fe30beSLoGin let v2 = iter.next().map(|v| v.trim()); 444*f9fe30beSLoGin let v3 = iter.next().map(|v| v.trim()); 445*f9fe30beSLoGin let v = [v1, v2, v3]; 446*f9fe30beSLoGin 447*f9fe30beSLoGin let mut key_split_len = 0; 448*f9fe30beSLoGin v.iter().for_each(|x| { 449*f9fe30beSLoGin if x.is_some() { 450*f9fe30beSLoGin key_split_len += 1 451*f9fe30beSLoGin } 452*f9fe30beSLoGin }); 453*f9fe30beSLoGin 454*f9fe30beSLoGin let (node, option) = match key_split_len { 455*f9fe30beSLoGin 1 => (None, v[0].unwrap()), 456*f9fe30beSLoGin 2 => (Some(v[0].unwrap()), v[1].unwrap()), 457*f9fe30beSLoGin _ => { 458*f9fe30beSLoGin log::warn!("cmdline: invalid argument: {}", arg); 459*f9fe30beSLoGin return None; 460*f9fe30beSLoGin } 461*f9fe30beSLoGin }; 462*f9fe30beSLoGin 463*f9fe30beSLoGin Some((node, option, value)) 464*f9fe30beSLoGin } 465*f9fe30beSLoGin 466*f9fe30beSLoGin fn split_args<'a>(&self, cmdline: &'a str) -> impl Iterator<Item = &'a str> { 467*f9fe30beSLoGin // 是否在引号内 468*f9fe30beSLoGin let mut in_quote = false; 469*f9fe30beSLoGin cmdline.split(move |c: char| { 470*f9fe30beSLoGin if c == '"' { 471*f9fe30beSLoGin in_quote = !in_quote; 472*f9fe30beSLoGin } 473*f9fe30beSLoGin !in_quote && c.is_whitespace() 474*f9fe30beSLoGin }) 475*f9fe30beSLoGin } 476*f9fe30beSLoGin } 477