#[derive(Default, Debug, Clone)]
#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LinuxKernelCommandLineParameters(HashMap<Box<[u8]>, Vec<Option<Box<[u8]>>>>);
impl LinuxKernelCommandLineParameters
{
#[inline(always)]
pub fn numa_balancing(&self) -> Option<bool>
{
self.get_value(b"numa_balancing").map(|value|
{
match value
{
b"enable" => true,
b"disable" => false,
_ => panic!("numa_balancing '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn noautogroup(&self) -> bool
{
self.is_present_with_no_value(b"noautogroup")
}
#[inline(always)]
pub fn noexec(&self) -> Option<bool>
{
self.get_value(b"noexec").map(|value|
{
match value
{
b"on" => true,
b"off" => false,
_ => panic!("noexec '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn noexec32(&self) -> Option<bool>
{
self.get_value(b"noexec32").map(|value|
{
match value
{
b"on" => true,
b"off" => false,
_ => panic!("noexec32 '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn skew_tick(&self) -> Option<bool>
{
self.get_value(b"skew_tick").map(|value|
{
match value
{
b"0" => false,
b"1" => true,
_ => panic!("skew_tick '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn hpet_mmap(&self) -> Option<bool>
{
self.get_value(b"hpet_mmap").map(|value|
{
match value
{
b"0" => false,
b"1" => true,
_ => panic!("hpet_mmap '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn vdso(&self) -> Option<bool>
{
self.get_value(b"vdso").map(|value|
{
match value
{
b"0" => false,
b"1" => true,
_ => panic!("vdso '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn vdso32(&self) -> Option<bool>
{
self.get_value(b"vdso32").map(|value|
{
match value
{
b"0" => false,
b"1" => true,
b"2" => false,
_ => panic!("vdso32 '{:?}' is unrecognised", value)
}
})
}
#[inline(always)]
pub fn isolcpus(&self) -> Option<(HashSet<IsolatedCpuFlags>, HyperThreads)>
{
self.get_value(b"isolcpus").map(|value|
{
let (flags_to_split, cpu_list) = IsolatedCpuFlags::split_flags_and_cpu_list(value);
let mut flags = HashSet::with_capacity(2);
match flags_to_split
{
None =>
{
flags.insert(IsolatedCpuFlags::Domain);
},
Some(flags_to_split) => for flag in flags_to_split.split_bytes(b',')
{
flags.insert(IsolatedCpuFlags::parse(flag).unwrap());
},
}
(flags, Self::parse_hyper_thread_list(cpu_list))
})
}
#[inline(always)]
pub fn rcu_nocbs(&self) -> Option<HyperThreads>
{
self.get_value(b"rcu_nocbs").map(Self::parse_hyper_thread_list)
}
#[inline(always)]
pub fn nohz_full(&self) -> Option<HyperThreads>
{
self.get_value(b"nohz_full").map(Self::parse_hyper_thread_list)
}
#[inline(always)]
pub fn irqaffinity(&self) -> Option<HyperThreads>
{
self.get_value(b"irqaffinity").map(Self::parse_hyper_thread_list)
}
#[inline(always)]
pub fn nosmp(&self) -> bool
{
self.is_present_with_no_value(b"nosmp")
}
#[inline(always)]
pub fn maxcpus(&self) -> Option<u16>
{
self.get_value_parsed(b"maxcpus")
}
#[inline(always)]
pub fn nr_cpus(&self) -> Option<u16>
{
self.get_value_parsed(b"nr_cpus")
}
#[inline(always)]
pub fn possible_cpus(&self) -> Option<u16>
{
self.get_value_parsed(b"possible_cpus")
}
#[inline(always)]
pub fn get_value_parsed<F: FromBytes>(&self, name: &'static [u8]) -> Option<F>
{
self.get_value(name).map(|bytes| F::from_bytes(bytes).unwrap())
}
#[inline(always)]
pub fn hashdist(&self) -> Option<bool>
{
self.get_value(b"hashdist").map(|value|
{
match value
{
b"0" => false,
b"1" => true,
_ => panic!("Unknown hashdist value '{:?}'", value),
}
})
}
#[inline(always)]
pub fn pci(&self) -> Option<HashSet<&[u8]>>
{
self.get_value(b"pci").map(|value|
{
value.split_bytes(b',').collect()
})
}
#[inline(always)]
pub fn acpi(&self) -> Option<&[u8]>
{
self.get_value(b"acpi")
}
#[inline(always)]
pub fn iommu(&self) -> Option<&[u8]>
{
self.get_value(b"iommu")
}
#[inline(always)]
pub fn intel_iommu(&self) -> Option<&[u8]>
{
self.get_value(b"intel_iommu")
}
#[inline(always)]
pub fn numa_zonelist_order(&self) -> Option<&[u8]>
{
self.get_value(b"numa_zonelist_order")
}
#[inline(always)]
pub fn numa(&self) -> Option<(&[u8], Option<&[u8]>)>
{
self.get_value(b"numa").map(|value|
{
let mut split = value.split_bytes_n(2, b'=');
(split.next().unwrap(), split.last())
})
}
#[inline(always)]
pub fn idle(&self) -> Option<&[u8]>
{
self.get_value(b"idle")
}
#[inline(always)]
pub fn nopcid(&self) -> bool
{
self.is_present_with_no_value(b"nopcid")
}
#[inline(always)]
pub fn noinvpcid(&self) -> bool
{
self.is_present_with_no_value(b"noinvpcid")
}
#[inline(always)]
pub fn norandmaps(&self) -> bool
{
self.is_present_with_no_value(b"norandmaps")
}
#[inline(always)]
pub fn noapic(&self) -> bool
{
self.is_present_with_no_value(b"noapic")
}
#[inline(always)]
pub fn disableapic(&self) -> bool
{
self.is_present_with_no_value(b"disableapic")
}
#[inline(always)]
pub fn nolapic(&self) -> bool
{
self.is_present_with_no_value(b"nolapic")
}
#[inline(always)]
pub fn noapictimer(&self) -> bool
{
self.is_present_with_no_value(b"noapictimer")
}
#[inline(always)]
pub fn nox2apic(&self) -> bool
{
self.is_present_with_no_value(b"nox2apic")
}
#[inline(always)]
pub fn nopat(&self) -> bool
{
self.is_present_with_no_value(b"nopat")
}
#[inline(always)]
pub fn noxsaveopt(&self) -> bool
{
self.is_present_with_no_value(b"noxsaveopt")
}
#[inline(always)]
pub fn noaliencache(&self) -> bool
{
self.is_present_with_no_value(b"noaliencache")
}
#[inline(always)]
pub fn movable_node(&self) -> bool
{
self.is_present_with_no_value(b"movable_node")
}
#[inline(always)]
pub fn nokaslr(&self) -> bool
{
self.is_present_with_no_value(b"nokaslr")
}
#[inline(always)]
pub fn nospectre_v2(&self) -> bool
{
self.is_present_with_no_value(b"nospectre_v2")
}
#[inline(always)]
pub fn spectre_v2(&self) -> Option<&[u8]>
{
self.get_value(b"spectre_v2")
}
#[inline(always)]
pub fn nopti(&self) -> bool
{
self.is_present_with_no_value(b"nopti")
}
#[inline(always)]
pub fn pti(&self) -> Option<&[u8]>
{
self.get_value(b"pti")
}
#[inline(always)]
pub fn vsyscall(&self) -> Option<&[u8]>
{
self.get_value(b"vsyscall")
}
#[inline(always)]
pub fn nohugeiomap(&self) -> bool
{
self.is_present_with_no_value(b"nohugeiomap")
}
#[inline(always)]
pub fn notsc(&self) -> bool
{
self.is_present_with_no_value(b"notsc")
}
#[inline(always)]
pub fn nohpet(&self) -> bool
{
self.is_present_with_no_value(b"nohpet")
}
#[inline(always)]
pub fn panic(&self) -> Option<i64>
{
self.get_value_parsed(b"panic")
}
#[inline(always)]
pub fn locale(&self) -> Option<&[u8]>
{
self.get_value(b"locale")
}
#[inline(always)]
pub fn root(&self) -> Option<(Option<&[u8]>, &[u8])>
{
self.get_value(b"root").map(|root|
{
let mut key_value = root.split_bytes_n(2, b'=');
let key_or_value = key_value.next().unwrap();
match key_value.next()
{
None => (None, key_or_value),
Some(value) => (Some(key_or_value), value)
}
})
}
#[inline(always)]
pub fn default_hugepagesz(&self) -> Option<&[u8]>
{
self.get_value(b"default_hugepagesz")
}
#[inline(always)]
pub fn hugepagesz(&self) -> Option<Vec<&[u8]>>
{
self.get_values(b"hugepagesz")
}
#[inline(always)]
pub fn hugepages(&self) -> Option<Vec<&[u8]>>
{
self.get_values(b"hugepages")
}
#[inline(always)]
pub fn selinux(&self) -> Option<bool>
{
self.get_value(b"selinux").map(|selinux|
{
match selinux
{
b"0" => false,
b"1" => true,
_ => panic!("Invalid value of selinux '{:?}'", selinux),
}
})
}
#[inline(always)]
pub fn modules(&self) -> Option<Vec<&[u8]>>
{
self.get_value(b"modules").map(|modules|
{
let mut set = Vec::new();
for module in modules.split_bytes(b',')
{
set.push(module)
}
set
})
}
#[inline(always)]
pub fn nomodeset(&self) -> bool
{
self.is_present_with_no_value(b"nomodeset")
}
#[inline(always)]
pub fn quiet(&self) -> bool
{
self.is_present_with_no_value(b"quiet")
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn S(&self) -> bool
{
self.is_present_with_no_value(b"S")
}
#[inline(always)]
pub fn single(&self) -> bool
{
self.is_present_with_no_value(b"single")
}
#[inline(always)]
pub fn debug(&self) -> bool
{
self.is_present_with_no_value(b"debug")
}
#[inline(always)]
pub fn ro(&self) -> bool
{
self.is_present_with_no_value(b"ro")
}
#[inline(always)]
pub fn rw(&self) -> bool
{
self.is_present_with_no_value(b"rw")
}
#[inline(always)]
pub fn nogbpages(&self) -> bool
{
self.is_present_with_no_value(b"nogbpages")
}
#[inline(always)]
pub fn gbpages(&self) -> bool
{
self.is_present_with_no_value(b"gbpages")
}
#[inline(always)]
pub fn initrd(&self) -> Option<&[u8]>
{
self.get_value(b"initrd")
}
#[inline(always)]
pub fn init(&self) -> Option<PathBuf>
{
self.get_value(b"init").map(|value| PathBuf::from(OsString::from_vec(value.to_vec())))
}
#[inline(always)]
pub fn rootfstype(&self) -> Option<FileSystemType>
{
self.get_value(b"rootfstype").map(|value| FileSystemType::from_byte_slice(value))
}
#[inline(always)]
pub fn console(&self) -> Option<Vec<&[u8]>>
{
self.get_values(b"console")
}
#[inline(always)]
pub fn is_present_with_no_value<'a, 'b>(&'b self, parameter_name: &'a [u8]) -> bool
{
match self.get(parameter_name)
{
None => false,
Some(ref list) =>
{
debug_assert_ne!(list.len(), 0, "list has no elements");
assert_eq!(list.len(), 1, "more than one value for parameter");
assert_eq!(list[0], None, "present with a value");
true
}
}
}
#[inline(always)]
pub fn get_value<'a, 'b>(&'b self, parameter_name: &'a [u8]) -> Option<&'b [u8]>
{
match self.get(parameter_name)
{
None => None,
Some(list) =>
{
debug_assert_ne!(list.len(), 0, "list has no elements");
assert_eq!(list.len(), 1, "more than one value for parameter");
list.get_unchecked_safe(0).as_ref().map(|value| &value[..])
}
}
}
#[inline(always)]
pub fn get_values<'a, 'b>(&'b self, parameter_name: &'a [u8]) -> Option<Vec<&'b [u8]>>
{
match self.get(parameter_name)
{
None => None,
Some(list) =>
{
debug_assert_ne!(list.len(), 0, "list has no elements");
let mut strings = Vec::with_capacity(list.len());
for index in 0 .. list.len()
{
strings.push(list.get_unchecked_safe(index).as_ref().map(|value| &value[..]).unwrap())
}
Some(strings)
}
}
}
#[inline(always)]
pub fn parse(proc_path: &ProcPath) -> io::Result<Self>
{
let file_path = proc_path.file_path("cmdline");
let line_of_parameters = file_path.read_raw_without_line_feed()?;
let mut map = HashMap::with_capacity(32);
for parameter in line_of_parameters.split_bytes(b' ')
{
let mut key_value = parameter.split_bytes_n(2, b'=');
let key = key_value.next().expect("There is no key");
if key.is_empty()
{
continue
}
let key = replace(key, b'-', b'_');
let entry = map.entry(key).or_insert_with(|| Vec::with_capacity(1));
let raw_value = key_value.next();
if raw_value.is_none()
{
entry.push(None);
continue
}
let potentially_quoted = raw_value.unwrap();
let value = if potentially_quoted.len() >= 2 && potentially_quoted.starts_with(b"\"") && potentially_quoted.ends_with(b"\"")
{
&potentially_quoted[1 .. (potentially_quoted.len() - 1)]
}
else
{
potentially_quoted
};
entry.push(Some(value.to_vec().into_boxed_slice()));
}
map.shrink_to_fit();
Ok(LinuxKernelCommandLineParameters(map))
}
#[inline(always)]
fn get<'a>(&self, parameter_name: &'a [u8]) -> Option<&Vec<Option<Box<[u8]>>>>
{
self.0.get(parameter_name)
}
#[inline(always)]
fn parse_hyper_thread_list(list: &[u8]) -> HyperThreads
{
HyperThreads(BitSet::<HyperThread>::parse_linux_list_string(list).unwrap())
}
}