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};
|
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 {
|
impl Ext2Fs {
|
||||||
pub async fn with_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
pub async fn with_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
||||||
&self,
|
&self,
|
||||||
@ -47,14 +63,19 @@ impl Ext2Fs {
|
|||||||
.await
|
.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,
|
&self,
|
||||||
inode: &Inode,
|
inode: &Inode,
|
||||||
block: u32,
|
block: u32,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
) -> Result<T, Error> {
|
) -> Result<T, Error> {
|
||||||
let block_index = self.inode_block_index(inode, block).await?;
|
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>>(
|
pub async fn with_inode_block_mut<T, F: FnOnce(&mut [u8]) -> Result<T, Error>>(
|
||||||
|
@ -9,7 +9,7 @@ use yggdrasil_abi::{
|
|||||||
util::FixedString,
|
util::FixedString,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{data::FsRequiredFeatures, Dirent, Ext2Fs};
|
use crate::{access::InodeBlock, data::FsRequiredFeatures, Dirent, Ext2Fs};
|
||||||
|
|
||||||
use super::DirentName;
|
use super::DirentName;
|
||||||
|
|
||||||
@ -110,8 +110,17 @@ impl<'a, D: DerefMut<Target = [u8]> + 'a> Record<'a, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DirentIter<'a> {
|
impl<'a> DirentIter<'a> {
|
||||||
pub fn new(fs: &'a Ext2Fs, block: &'a [u8], offset: usize) -> Self {
|
pub fn new(fs: &'a Ext2Fs, block: InodeBlock<'a>, offset: usize) -> Self {
|
||||||
Self { fs, block, offset }
|
let data = if let InodeBlock::Data(data) = block {
|
||||||
|
data
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
fs,
|
||||||
|
block: data,
|
||||||
|
offset,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> usize {
|
||||||
|
@ -15,7 +15,8 @@ use yggdrasil_abi::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
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 {
|
pub struct InodeHolder {
|
||||||
@ -103,7 +104,7 @@ impl InodeAccess {
|
|||||||
result
|
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,
|
&self,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
) -> Result<Option<T>, Error> {
|
) -> Result<Option<T>, Error> {
|
||||||
|
@ -390,12 +390,17 @@ impl Ext2Fs {
|
|||||||
let block_offset = (pos % self.block_size as u64) as usize;
|
let block_offset = (pos % self.block_size as u64) as usize;
|
||||||
let amount = remaining.min(self.block_size - block_offset);
|
let amount = remaining.min(self.block_size - block_offset);
|
||||||
|
|
||||||
self.with_inode_block(inode, block_index as u32, |block| {
|
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]
|
buffer[offset..offset + amount]
|
||||||
.copy_from_slice(&block[block_offset..block_offset + amount]);
|
.copy_from_slice(&block[block_offset..block_offset + amount]);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
pos += amount as u64;
|
pos += amount as u64;
|
||||||
offset += amount;
|
offset += amount;
|
||||||
|
@ -54,8 +54,9 @@ impl SymlinkNode {
|
|||||||
} else {
|
} else {
|
||||||
self.fs
|
self.fs
|
||||||
.with_inode_block(inode, 0, |block| {
|
.with_inode_block(inode, 0, |block| {
|
||||||
write.extend_from_slice(&block[..len]);
|
write.resize(len, 0);
|
||||||
buf[..len].copy_from_slice(&block[..len]);
|
block.copy_to(0, &mut write[..]);
|
||||||
|
block.copy_to(0, &mut buf[..len]);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user