ext2: support reading from files with holes
This commit is contained in:
parent
dcc5d56750
commit
a1ccdf7e76
@ -2,6 +2,22 @@ use libk::error::Error;
|
||||
|
||||
use crate::{BlockGroupDescriptor, Ext2Fs, ExtendedSuperblock, Inode};
|
||||
|
||||
pub enum InodeBlock<'a> {
|
||||
Hole,
|
||||
Data(&'a [u8]),
|
||||
}
|
||||
|
||||
impl InodeBlock<'_> {
|
||||
pub fn copy_to(&self, offset: usize, destination: &mut [u8]) {
|
||||
match self {
|
||||
Self::Hole => destination.fill(0),
|
||||
Self::Data(data) => {
|
||||
destination.copy_from_slice(&data[offset..offset + destination.len()])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ext2Fs {
|
||||
pub async fn with_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
||||
&self,
|
||||
@ -47,14 +63,19 @@ impl Ext2Fs {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn with_inode_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
||||
pub async fn with_inode_block<T, F: FnOnce(InodeBlock) -> Result<T, Error>>(
|
||||
&self,
|
||||
inode: &Inode,
|
||||
block: u32,
|
||||
mapper: F,
|
||||
) -> Result<T, Error> {
|
||||
let block_index = self.inode_block_index(inode, block).await?;
|
||||
self.with_block(block_index, mapper).await
|
||||
if block_index == 0 {
|
||||
mapper(InodeBlock::Hole)
|
||||
} else {
|
||||
self.with_block(block_index, |block| mapper(InodeBlock::Data(block)))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn with_inode_block_mut<T, F: FnOnce(&mut [u8]) -> Result<T, Error>>(
|
||||
|
@ -9,7 +9,7 @@ use yggdrasil_abi::{
|
||||
util::FixedString,
|
||||
};
|
||||
|
||||
use crate::{data::FsRequiredFeatures, Dirent, Ext2Fs};
|
||||
use crate::{access::InodeBlock, data::FsRequiredFeatures, Dirent, Ext2Fs};
|
||||
|
||||
use super::DirentName;
|
||||
|
||||
@ -110,8 +110,17 @@ impl<'a, D: DerefMut<Target = [u8]> + 'a> Record<'a, D> {
|
||||
}
|
||||
|
||||
impl<'a> DirentIter<'a> {
|
||||
pub fn new(fs: &'a Ext2Fs, block: &'a [u8], offset: usize) -> Self {
|
||||
Self { fs, block, offset }
|
||||
pub fn new(fs: &'a Ext2Fs, block: InodeBlock<'a>, offset: usize) -> Self {
|
||||
let data = if let InodeBlock::Data(data) = block {
|
||||
data
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
Self {
|
||||
fs,
|
||||
block: data,
|
||||
offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> usize {
|
||||
|
@ -15,7 +15,8 @@ use yggdrasil_abi::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
data::InodeMode, dir::DirectoryNode, file::RegularNode, symlink::SymlinkNode, Ext2Fs, Inode,
|
||||
access::InodeBlock, data::InodeMode, dir::DirectoryNode, file::RegularNode,
|
||||
symlink::SymlinkNode, Ext2Fs, Inode,
|
||||
};
|
||||
|
||||
pub struct InodeHolder {
|
||||
@ -103,7 +104,7 @@ impl InodeAccess {
|
||||
result
|
||||
}
|
||||
|
||||
pub async fn map_blocks<T, F: Fn(&Inode, usize, &[u8]) -> Result<Option<T>, Error>>(
|
||||
pub async fn map_blocks<T, F: Fn(&Inode, usize, InodeBlock) -> Result<Option<T>, Error>>(
|
||||
&self,
|
||||
mapper: F,
|
||||
) -> Result<Option<T>, Error> {
|
||||
|
@ -390,12 +390,17 @@ impl Ext2Fs {
|
||||
let block_offset = (pos % self.block_size as u64) as usize;
|
||||
let amount = remaining.min(self.block_size - block_offset);
|
||||
|
||||
self.with_inode_block(inode, block_index as u32, |block| {
|
||||
buffer[offset..offset + amount]
|
||||
.copy_from_slice(&block[block_offset..block_offset + amount]);
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
let block = self.inode_block_index(inode, block_index as u32).await?;
|
||||
if block == 0 {
|
||||
buffer[offset..offset + amount].fill(0);
|
||||
} else {
|
||||
self.with_block(block, |block| {
|
||||
buffer[offset..offset + amount]
|
||||
.copy_from_slice(&block[block_offset..block_offset + amount]);
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
|
||||
pos += amount as u64;
|
||||
offset += amount;
|
||||
|
@ -54,8 +54,9 @@ impl SymlinkNode {
|
||||
} else {
|
||||
self.fs
|
||||
.with_inode_block(inode, 0, |block| {
|
||||
write.extend_from_slice(&block[..len]);
|
||||
buf[..len].copy_from_slice(&block[..len]);
|
||||
write.resize(len, 0);
|
||||
block.copy_to(0, &mut write[..]);
|
||||
block.copy_to(0, &mut buf[..len]);
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user