Optimize the CpioEntry to send data to the Write trait
This commit is contained in:
parent
4b3cf8daeb
commit
13c4c614b5
|
@ -177,6 +177,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"core2",
|
||||
"int-to-c-enum",
|
||||
"lending-iterator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -285,6 +286,35 @@ version = "1.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "ext-trait"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5"
|
||||
dependencies = [
|
||||
"ext-trait-proc_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ext-trait-proc_macros"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "extension-traits"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537"
|
||||
dependencies = [
|
||||
"ext-trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -575,6 +605,7 @@ dependencies = [
|
|||
"ascii",
|
||||
"bitflags",
|
||||
"controlled",
|
||||
"core2",
|
||||
"cpio-decoder",
|
||||
"getrandom",
|
||||
"int-to-c-enum",
|
||||
|
@ -589,6 +620,7 @@ dependencies = [
|
|||
"jinux-util",
|
||||
"keyable-arc",
|
||||
"lazy_static",
|
||||
"lending-iterator",
|
||||
"libflate",
|
||||
"log",
|
||||
"lru",
|
||||
|
@ -661,6 +693,31 @@ dependencies = [
|
|||
"spin 0.5.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lending-iterator"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc07588c853b50689205fb5c00498aa681d89828e0ce8cbd965ebc7a5d8ae260"
|
||||
dependencies = [
|
||||
"extension-traits",
|
||||
"lending-iterator-proc_macros",
|
||||
"macro_rules_attribute",
|
||||
"never-say-never",
|
||||
"nougat",
|
||||
"polonius-the-crab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lending-iterator-proc_macros"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5445dd1c0deb1e97b8a16561d17fc686ca83e8411128fb036e9668a72d51b1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.146"
|
||||
|
@ -725,6 +782,22 @@ dependencies = [
|
|||
"hashbrown 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro_rules_attribute"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862"
|
||||
dependencies = [
|
||||
"macro_rules_attribute-proc_macro",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro_rules_attribute-proc_macro"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d"
|
||||
|
||||
[[package]]
|
||||
name = "managed"
|
||||
version = "0.8.0"
|
||||
|
@ -746,12 +819,45 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "never-say-never"
|
||||
version = "6.6.666"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf5a574dadd7941adeaa71823ecba5e28331b8313fb2e1c6a5c7e5981ea53ad6"
|
||||
|
||||
[[package]]
|
||||
name = "nougat"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b57b9ced431322f054fc673f1d3c7fa52d80efd9df74ad2fc759f044742510"
|
||||
dependencies = [
|
||||
"macro_rules_attribute",
|
||||
"nougat-proc_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nougat-proc_macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c84f77a45e99a2f9b492695d99e1c23844619caa5f3e57647cffacad773ca257"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "pod"
|
||||
version = "0.1.0"
|
||||
|
@ -770,6 +876,12 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polonius-the-crab"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a69ee997a6282f8462abf1e0d8c38c965e968799e912b3bed8c9e8a28c2f9f"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
|
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
int-to-c-enum = { path = "../../libs/int-to-c-enum" }
|
||||
core2 = { version = "0.4", default_features = false, features = ["alloc"] }
|
||||
core2 = { version = "0.4", default_features = false, features = ["alloc"] }
|
||||
lending-iterator = "0.1.7"
|
|
@ -9,4 +9,17 @@ pub enum Error {
|
|||
FileTypeError,
|
||||
FileNameError,
|
||||
BufferShortError,
|
||||
IoError,
|
||||
}
|
||||
|
||||
impl From<core2::io::Error> for Error {
|
||||
#[inline]
|
||||
fn from(err: core2::io::Error) -> Self {
|
||||
use core2::io::ErrorKind;
|
||||
|
||||
match err.kind() {
|
||||
ErrorKind::UnexpectedEof => Self::BufferShortError,
|
||||
_ => Self::IoError,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
//!
|
||||
//! ```rust
|
||||
//! use cpio_decoder::CpioDecoder;
|
||||
//! use lending_iterator::LendingIterator;
|
||||
//!
|
||||
//! let short_buffer: Vec<u8> = Vec::new();
|
||||
//! let mut decoder = CpioDecoder::new(short_buffer.as_slice());
|
||||
//! for entry_result in decoder.decode_entries() {
|
||||
//! if let Some(entry_result) = decoder.next() {
|
||||
//! println!("The entry_result is: {:?}", entry_result);
|
||||
//! }
|
||||
//! ```
|
||||
|
@ -21,16 +22,17 @@ extern crate alloc;
|
|||
use crate::error::{Error, Result};
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use core2::io::Read;
|
||||
use core::cmp::min;
|
||||
use core2::io::{Read, Write};
|
||||
use int_to_c_enum::TryFromInt;
|
||||
use lending_iterator::prelude::*;
|
||||
|
||||
pub mod error;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
/// A CPIO (the newc format) decoder.
|
||||
/// A CPIO (the newc format) decoder to iterator over the results of CPIO entries.
|
||||
///
|
||||
/// "newc" is the new portable format and CRC format.
|
||||
///
|
||||
|
@ -41,37 +43,16 @@ mod test;
|
|||
/// All the fields in the header are ISO 646 (approximately ASCII) strings
|
||||
/// of hexadecimal numbers, left padded, not NULL terminated.
|
||||
pub struct CpioDecoder<R> {
|
||||
inner: R,
|
||||
reader: R,
|
||||
is_error: bool,
|
||||
}
|
||||
|
||||
impl<R> CpioDecoder<R>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
/// create a decoder to decode the CPIO.
|
||||
pub fn new(inner: R) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
/// Return an iterator trying to decode the entries in the CPIO.
|
||||
pub fn decode_entries(&mut self) -> CpioEntryIter<R> {
|
||||
CpioEntryIter::new(&mut self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the results of CPIO entries.
|
||||
///
|
||||
/// It stops if reaches to the trailer entry or encounters an error.
|
||||
pub struct CpioEntryIter<'a, R> {
|
||||
reader: &'a mut R,
|
||||
is_error: bool,
|
||||
}
|
||||
|
||||
impl<'a, R> CpioEntryIter<'a, R>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
fn new(reader: &'a mut R) -> Self {
|
||||
/// Create a decoder.
|
||||
pub fn new(reader: R) -> Self {
|
||||
Self {
|
||||
reader,
|
||||
is_error: false,
|
||||
|
@ -79,19 +60,21 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, R> Iterator for CpioEntryIter<'a, R>
|
||||
#[gat]
|
||||
impl<R> LendingIterator for CpioDecoder<R>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
type Item = Result<CpioEntry>;
|
||||
type Item<'a> = Result<CpioEntry<'a, R>>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<CpioEntry>> {
|
||||
/// Stops if reaches to the trailer entry or encounters an error.
|
||||
fn next<'a>(self: &'a mut Self) -> Option<Self::Item<'a>> {
|
||||
// Stop to iterate entries if encounters an error.
|
||||
if self.is_error {
|
||||
return None;
|
||||
}
|
||||
|
||||
let entry_result = CpioEntry::new(self.reader);
|
||||
let entry_result = CpioEntry::new(&mut self.reader);
|
||||
match &entry_result {
|
||||
Ok(entry) => {
|
||||
// A correct CPIO buffer must end with a trailer.
|
||||
|
@ -109,25 +92,24 @@ where
|
|||
|
||||
/// A file entry in the CPIO.
|
||||
#[derive(Debug)]
|
||||
pub struct CpioEntry {
|
||||
pub struct CpioEntry<'a, R> {
|
||||
metadata: FileMetadata,
|
||||
name: String,
|
||||
data: Vec<u8>,
|
||||
reader: &'a mut R,
|
||||
data_padding_len: usize,
|
||||
}
|
||||
|
||||
impl CpioEntry {
|
||||
fn new<R>(reader: &mut R) -> Result<Self>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
let (metadata, name, data) = {
|
||||
impl<'a, R> CpioEntry<'a, R>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
fn new(reader: &'a mut R) -> Result<Self> {
|
||||
let (metadata, name, data_padding_len) = {
|
||||
let header = Header::new(reader)?;
|
||||
let name = {
|
||||
let name_size = read_hex_bytes_to_u32(&header.name_size)? as usize;
|
||||
let mut name_bytes = vec![0u8; name_size];
|
||||
reader
|
||||
.read_exact(&mut name_bytes)
|
||||
.map_err(|_| Error::BufferShortError)?;
|
||||
reader.read_exact(&mut name_bytes)?;
|
||||
let name = core::ffi::CStr::from_bytes_with_nul(&name_bytes)
|
||||
.map_err(|_| Error::FileNameError)?;
|
||||
name.to_str().map_err(|_| Error::Utf8Error)?.to_string()
|
||||
|
@ -137,38 +119,22 @@ impl CpioEntry {
|
|||
} else {
|
||||
FileMetadata::new(&header)?
|
||||
};
|
||||
let data = {
|
||||
let pad_header_len = align_up_pad(header.len() + name.len() + 1, 4);
|
||||
if pad_header_len > 0 {
|
||||
let mut pad_buf = vec![0u8; pad_header_len];
|
||||
reader
|
||||
.read_exact(&mut pad_buf)
|
||||
.map_err(|_| Error::BufferShortError)?;
|
||||
let data_padding_len = {
|
||||
let header_padding_len = align_up_pad(header.len() + name.len() + 1, 4);
|
||||
if header_padding_len > 0 {
|
||||
let mut pad_buf = vec![0u8; header_padding_len];
|
||||
reader.read_exact(&mut pad_buf)?;
|
||||
}
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
let data_size = metadata.size as usize;
|
||||
if data_size > 0 {
|
||||
data.resize_with(data_size, Default::default);
|
||||
reader
|
||||
.read_exact(&mut data)
|
||||
.map_err(|_| Error::BufferShortError)?;
|
||||
}
|
||||
data
|
||||
align_up_pad(metadata.size() as usize, 4)
|
||||
};
|
||||
let pad_data_len = align_up_pad(data.len(), 4);
|
||||
if pad_data_len > 0 {
|
||||
let mut pad_buf = vec![0u8; pad_data_len];
|
||||
reader
|
||||
.read_exact(&mut pad_buf)
|
||||
.map_err(|_| Error::BufferShortError)?;
|
||||
}
|
||||
|
||||
(metadata, name, data)
|
||||
(metadata, name, data_padding_len)
|
||||
};
|
||||
Ok(Self {
|
||||
metadata,
|
||||
name,
|
||||
data,
|
||||
reader,
|
||||
data_padding_len,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -182,12 +148,28 @@ impl CpioEntry {
|
|||
&self.name
|
||||
}
|
||||
|
||||
/// The data of the file.
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
/// Read all data to the writer.
|
||||
pub fn read_all<W>(&mut self, mut writer: W) -> Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let data_len = self.metadata().size() as usize;
|
||||
let mut send_len = 0;
|
||||
let mut buffer = vec![0u8; 0x1000];
|
||||
while send_len < data_len {
|
||||
let len = min(buffer.len(), data_len - send_len);
|
||||
self.reader.read_exact(&mut buffer[..len])?;
|
||||
writer.write_all(&mut buffer[..len])?;
|
||||
send_len += len;
|
||||
}
|
||||
if self.data_padding_len > 0 {
|
||||
self.reader
|
||||
.read_exact(&mut buffer[..self.data_padding_len])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_trailer(&self) -> bool {
|
||||
pub fn is_trailer(&self) -> bool {
|
||||
&self.name == TRAILER_NAME
|
||||
}
|
||||
}
|
||||
|
@ -344,9 +326,7 @@ impl Header {
|
|||
R: Read,
|
||||
{
|
||||
let mut buf = vec![0u8; core::mem::size_of::<Self>()];
|
||||
reader
|
||||
.read_exact(&mut buf)
|
||||
.map_err(|_| Error::BufferShortError)?;
|
||||
reader.read_exact(&mut buf)?;
|
||||
|
||||
let header = Self {
|
||||
magic: <[u8; 6]>::try_from(&buf[0..6]).unwrap(),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::error::*;
|
||||
use super::{CpioDecoder, FileType};
|
||||
use lending_iterator::LendingIterator;
|
||||
|
||||
#[test]
|
||||
fn test_decoder() {
|
||||
|
@ -24,48 +25,55 @@ fn test_decoder() {
|
|||
output.stdout
|
||||
};
|
||||
|
||||
assert!(CpioDecoder::new(buffer.as_slice()).decode_entries().count() > 3);
|
||||
let mut decoder = CpioDecoder::new(buffer.as_slice());
|
||||
for (idx, entry_result) in decoder.decode_entries().enumerate() {
|
||||
let entry = entry_result.unwrap();
|
||||
if idx == 0 {
|
||||
assert!(entry.name() == ".");
|
||||
assert!(entry.metadata().file_type() == FileType::Dir);
|
||||
assert!(entry.metadata().ino() > 0);
|
||||
}
|
||||
if idx == 1 {
|
||||
assert!(entry.name() == "src");
|
||||
assert!(entry.metadata().file_type() == FileType::Dir);
|
||||
assert!(entry.metadata().ino() > 0);
|
||||
}
|
||||
if idx == 2 {
|
||||
assert!(
|
||||
entry.name() == "src/lib.rs"
|
||||
|| entry.name() == "src/test.rs"
|
||||
|| entry.name() == "src/error.rs"
|
||||
);
|
||||
assert!(entry.metadata().file_type() == FileType::File);
|
||||
assert!(entry.metadata().ino() > 0);
|
||||
}
|
||||
}
|
||||
// 1st entry
|
||||
let entry = {
|
||||
let entry_result = decoder.next().unwrap();
|
||||
entry_result.unwrap()
|
||||
};
|
||||
assert!(entry.name() == ".");
|
||||
assert!(entry.metadata().file_type() == FileType::Dir);
|
||||
assert!(entry.metadata().ino() > 0);
|
||||
// 2nd entry
|
||||
let entry = {
|
||||
let entry_result = decoder.next().unwrap();
|
||||
entry_result.unwrap()
|
||||
};
|
||||
assert!(entry.name() == "src");
|
||||
assert!(entry.metadata().file_type() == FileType::Dir);
|
||||
assert!(entry.metadata().ino() > 0);
|
||||
|
||||
// 3rd entry
|
||||
let mut entry = {
|
||||
let entry_result = decoder.next().unwrap();
|
||||
entry_result.unwrap()
|
||||
};
|
||||
assert!(
|
||||
entry.name() == "src/lib.rs"
|
||||
|| entry.name() == "src/test.rs"
|
||||
|| entry.name() == "src/error.rs"
|
||||
);
|
||||
assert!(entry.metadata().file_type() == FileType::File);
|
||||
assert!(entry.metadata().ino() > 0);
|
||||
assert!(entry.metadata().size() > 0);
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
assert!(entry.read_all(&mut buffer).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_short_buffer() {
|
||||
let short_buffer: Vec<u8> = Vec::new();
|
||||
let mut decoder = CpioDecoder::new(short_buffer.as_slice());
|
||||
for entry_result in decoder.decode_entries() {
|
||||
assert!(entry_result.is_err());
|
||||
assert!(entry_result.err() == Some(Error::BufferShortError));
|
||||
}
|
||||
let entry_result = decoder.next().unwrap();
|
||||
assert!(entry_result.is_err());
|
||||
assert!(entry_result.err() == Some(Error::BufferShortError));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_buffer() {
|
||||
let buffer: &[u8] = b"invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic";
|
||||
let mut decoder = CpioDecoder::new(buffer);
|
||||
for entry_result in decoder.decode_entries() {
|
||||
assert!(entry_result.is_err());
|
||||
assert!(entry_result.err() == Some(Error::MagicError));
|
||||
}
|
||||
let entry_result = decoder.next().unwrap();
|
||||
assert!(entry_result.is_err());
|
||||
assert!(entry_result.err() == Some(Error::MagicError));
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ ringbuf = { version = "0.3.2", default-features = false, features = ["alloc"] }
|
|||
keyable-arc = { path = "../keyable-arc" }
|
||||
# unzip initramfs
|
||||
libflate = { git = "https://github.com/jinzhao-dev/libflate", rev = "b781da6", features = ["no_std"] }
|
||||
|
||||
core2 = { version = "0.4", default_features = false, features = ["alloc"] }
|
||||
lending-iterator = "0.1.7"
|
||||
spin = "0.9.4"
|
||||
vte = "0.10"
|
||||
lru = "0.9.0"
|
||||
|
|
|
@ -232,6 +232,9 @@ impl From<cpio_decoder::error::Error> for Error {
|
|||
cpio_decoder::error::Error::BufferShortError => {
|
||||
Error::with_message(Errno::EINVAL, "CPIO buffer is too short")
|
||||
}
|
||||
cpio_decoder::error::Error::IoError => {
|
||||
Error::with_message(Errno::EIO, "CPIO buffer I/O error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ 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.
|
||||
|
@ -13,8 +14,13 @@ pub fn init(gzip_ramdisk_buf: &[u8]) -> Result<()> {
|
|||
GZipDecoder::new(gzip_ramdisk_buf)
|
||||
.map_err(|_| Error::with_message(Errno::EINVAL, "invalid gzip buffer"))?,
|
||||
);
|
||||
for entry_result in decoder.decode_entries() {
|
||||
let entry = entry_result?;
|
||||
|
||||
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('/');
|
||||
|
@ -40,18 +46,22 @@ pub fn init(gzip_ramdisk_buf: &[u8]) -> Result<()> {
|
|||
match metadata.file_type() {
|
||||
FileType::File => {
|
||||
let dentry = parent.create(name, InodeType::File, mode)?;
|
||||
dentry.vnode().write_at(0, entry.data())?;
|
||||
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 = core::str::from_utf8(entry.data())?;
|
||||
dentry.vnode().write_link(link_content)?;
|
||||
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_ => {
|
||||
warn!("unsupported file type = {:?} in initramfs", type_);
|
||||
panic!("unsupported file type = {:?} in initramfs", type_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ pub use ioctl::IoctlCmd;
|
|||
pub use page_cache::PageCache;
|
||||
pub use poll::{Pollee, Poller};
|
||||
pub use status_flags::StatusFlags;
|
||||
pub use vnode::Vnode;
|
||||
pub use vnode::{Vnode, VnodeWriter};
|
||||
|
||||
mod access_mode;
|
||||
mod channel;
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::vm::vmo::Vmo;
|
|||
|
||||
use alloc::string::String;
|
||||
use core::time::Duration;
|
||||
use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write};
|
||||
use jinux_frame::vm::VmIo;
|
||||
use jinux_rights::Full;
|
||||
|
||||
|
@ -245,4 +246,33 @@ impl Vnode {
|
|||
pub fn is_dentry_cacheable(&self) -> bool {
|
||||
self.inner.read().inode.is_dentry_cacheable()
|
||||
}
|
||||
|
||||
pub fn writer(&self, from_offset: usize) -> VnodeWriter {
|
||||
VnodeWriter {
|
||||
inner: &self,
|
||||
offset: from_offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VnodeWriter<'a> {
|
||||
inner: &'a Vnode,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> Write for VnodeWriter<'a> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
||||
let write_len = self
|
||||
.inner
|
||||
.write_at(self.offset, buf)
|
||||
.map_err(|_| IoError::new(IoErrorKind::WriteZero, "failed to write buffer"))?;
|
||||
self.offset += write_len;
|
||||
Ok(write_len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ impl VmoInner {
|
|||
if self.should_share_frame_with_parent(write_page) {
|
||||
return Ok(inherited_frame);
|
||||
}
|
||||
|
||||
|
||||
let frame = {
|
||||
let options = VmAllocOptions::new(1);
|
||||
VmFrameVec::allocate(&options)?.pop().unwrap()
|
||||
|
|
Loading…
Reference in New Issue