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