use std::ffi::CStr;
use std::fs::File;
use std::io;
use std::io::Read as _;
use std::mem::MaybeUninit;
use std::path::Path;
use anyhow::Context as _;
use anyhow::Result;
use anyhow::bail;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum KernelFormat {
Elf = 1,
Bz2 = 3,
Gz = 4,
Zstd = 5,
}
pub fn detect_kernel_format(path: &Path) -> Result<KernelFormat> {
let mut magic = [0u8; 4];
let () = File::open(path)
.and_then(|mut f| f.read_exact(&mut magic))
.with_context(|| format!("failed to read kernel header from `{}`", path.display()))?;
let format = match magic {
[0x7f, b'E', b'L', b'F'] => KernelFormat::Elf,
[0x1f, 0x8b, ..] => KernelFormat::Gz,
[b'B', b'Z', b'h', _] => KernelFormat::Bz2,
[0x28, 0xb5, 0x2f, 0xfd] => KernelFormat::Zstd,
_ => bail!(
"unrecognized kernel format (magic: {magic:02x?}) for `{}`",
path.display()
),
};
Ok(format)
}
pub fn hostname() -> Result<String> {
const HOST_NAME_MAX: usize = 256;
let mut buf = MaybeUninit::<[u8; HOST_NAME_MAX]>::uninit();
let rc = unsafe { libc::gethostname(buf.as_mut_ptr().cast(), HOST_NAME_MAX) };
if rc != 0 {
return Err(io::Error::last_os_error()).context("failed to retrieve host name")
}
let _nul = <MaybeUninit<[_; _]> as AsMut<[MaybeUninit<_>; _]>>::as_mut(&mut buf)
.last_mut()
.unwrap()
.write(b'\0');
let hostname = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }
.to_string_lossy()
.into_owned();
Ok(hostname)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hostname_retrieval() {
let host_name = hostname().unwrap();
assert_ne!(host_name, "");
}
}