use super::*;
pub struct FileEditFile<'a> {
pub(super) file: &'a fs::File,
pub(super) desc: &'a mut Descriptor,
pub(super) high_mark: &'a mut u32,
}
impl<'a> FileEditFile<'a> {
#[inline]
pub fn descriptor(&self) -> &Descriptor {
self.desc
}
#[inline]
pub fn set_content(&mut self, content_type: u32, content_size: u32) -> &mut FileEditFile<'a> {
self.desc.content_type = u32::max(1, content_type); self.desc.content_size = content_size;
return self;
}
#[inline]
pub fn set_section(&mut self, section: &Section) -> &mut FileEditFile<'a> {
self.desc.section = *section;
return self;
}
pub fn allocate_data(&mut self) -> &mut FileEditFile<'a> {
self.desc.section.offset = *self.high_mark;
self.desc.section.size = bytes2blocks(self.desc.content_size);
*self.high_mark = self.high_mark.checked_add(self.desc.section.size).expect("PAKS file too large");
return self;
}
pub fn write_data(&mut self, data: &[u8], key: &Key) -> io::Result<&mut FileEditFile<'a>> {
let file_offset = self.desc.section.offset as u64 * BLOCK_SIZE as u64;
self.file.seek(io::SeekFrom::Start(file_offset))?;
let mut blocks = vec![Block::default(); self.desc.section.size as usize];
let len = usize::min(dataview::bytes(blocks.as_slice()).len(), data.len());
dataview::bytes_mut(blocks.as_mut_slice())[..len].copy_from_slice(&data[..len]);
crypt::encrypt_section(&mut blocks, &mut self.desc.section, key);
let result = self.file.write_all(dataview::bytes(blocks.as_slice()));
drop(blocks);
result.map(|()| self)
}
pub fn zero_data(&mut self, key: &Key) -> io::Result<&mut FileEditFile<'a>> {
let file_offset = self.desc.section.offset as u64 * BLOCK_SIZE as u64;
self.file.seek(io::SeekFrom::Start(file_offset))?;
let mut blocks = vec![Block::default(); self.desc.section.size as usize];
crypt::encrypt_section(&mut blocks, &mut self.desc.section, key);
let result = self.file.write_all(dataview::bytes(blocks.as_slice()));
drop(blocks);
result.map(|()| self)
}
pub fn reencrypt_data(&mut self, old_key: &Key, key: &Key) -> io::Result<()> {
let file_offset = self.desc.section.offset as u64 * BLOCK_SIZE as u64;
self.file.seek(io::SeekFrom::Start(file_offset))?;
let mut blocks = vec![Block::default(); self.desc.section.size as usize];
self.file.read_exact(dataview::bytes_mut(blocks.as_mut_slice()))?;
if !crypt::decrypt_section(&mut blocks, &self.desc.section, old_key) {
Err(io::ErrorKind::InvalidData)?;
}
crypt::encrypt_section(&mut blocks, &mut self.desc.section, key);
self.file.seek(io::SeekFrom::Start(file_offset))?;
self.file.write_all(dataview::bytes(blocks.as_slice()))?;
Ok(())
}
}