Files
asterinas/services/libs/jinux-std/src/fs/initramfs.rs

72 lines
2.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use super::fs_resolver::{FsPath, FsResolver};
use super::utils::{InodeMode, InodeType};
use crate::prelude::*;
use cpio_decoder::{CpioDecoder, FileType};
use lending_iterator::LendingIterator;
use libflate::gzip::Decoder as GZipDecoder;
/// Unpack and prepare the fs from the ramdisk CPIO buffer.
pub fn init(gzip_ramdisk_buf: &[u8]) -> Result<()> {
println!("[kernel] unzipping ramdisk.cpio.gz ...");
let fs = FsResolver::new();
let mut decoder = CpioDecoder::new(
GZipDecoder::new(gzip_ramdisk_buf)
.map_err(|_| Error::with_message(Errno::EINVAL, "invalid gzip buffer"))?,
);
loop {
let Some(entry_result) = decoder.next() else {
break;
};
let mut entry = entry_result?;
// Make sure the name is a relative path, and is not end with "/".
let entry_name = entry.name().trim_start_matches('/').trim_end_matches('/');
if entry_name.is_empty() {
return_errno_with_message!(Errno::EINVAL, "invalid entry name");
}
if entry_name == "." {
continue;
}
// Here we assume that the directory referred by "prefix" must has been created.
// The basis of this assumption is
// The mkinitramfs script uses `find` command to ensure that the entries are
// sorted that a directory always appears before its child directories and files.
let (parent, name) = if let Some((prefix, last)) = entry_name.rsplit_once('/') {
(fs.lookup(&FsPath::try_from(prefix)?)?, last)
} else {
(fs.root().clone(), entry_name)
};
let metadata = entry.metadata();
let mode = InodeMode::from_bits_truncate(metadata.permission_mode());
match metadata.file_type() {
FileType::File => {
let dentry = parent.create(name, InodeType::File, mode)?;
entry.read_all(dentry.vnode().writer(0))?;
}
FileType::Dir => {
let _ = parent.create(name, InodeType::Dir, mode)?;
}
FileType::Link => {
let dentry = parent.create(name, InodeType::SymLink, mode)?;
let link_content = {
let mut link_data: Vec<u8> = Vec::new();
entry.read_all(&mut link_data)?;
core::str::from_utf8(&link_data)?.to_string()
};
dentry.vnode().write_link(&link_content)?;
}
type_ => {
panic!("unsupported file type = {:?} in initramfs", type_);
}
}
}
println!("[kernel] initramfs is ready");
Ok(())
}