transfert file from zip to another (wip)

This commit is contained in:
Jean-Marie Mineau 2024-01-17 13:57:01 +01:00
parent 0d305fbe62
commit 0fdf619360
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
10 changed files with 512 additions and 273 deletions

View file

@ -0,0 +1,73 @@
use std::io::{Read, Seek, SeekFrom, Write};
use crate::{
end_of_central_directory::EndCentralDirectory,
end_of_central_directory::Zip64EndCentralDirectory, FileInfo, ZipFileReader,
};
use androscalpel_serializer::Serializable;
pub struct ZipFileWriter<T: Write> {
files: Vec<FileInfo>,
zip64_end_of_central_directory: Option<Zip64EndCentralDirectory>,
current_offset: u64,
data: T,
}
impl<T: Write> ZipFileWriter<T> {
pub fn new(writer: T, zip64_info: Option<Zip64EndCentralDirectory>) -> Self {
Self {
current_offset: 0,
zip64_end_of_central_directory: zip64_info,
files: vec![],
data: writer,
}
}
/// Insert an file from an existing zip
pub fn insert_file_from_zip<U: Read + Seek>(
&mut self,
mut file_info: FileInfo,
zip_file: &mut ZipFileReader<U>,
) {
let file_off = file_info.get_file_offset();
let file_size = file_info.get_compressed_size();
file_info.set_offset_local_header(self.current_offset);
file_info.local_header.serialize(&mut self.data).unwrap();
zip_file.data.seek(SeekFrom::Start(file_off)).unwrap();
let mut remaining_size = file_size;
let mut buffer = [0u8; 4096];
while remaining_size != 0 {
let read = zip_file
.data
.read(&mut buffer[0..core::cmp::min(4096, remaining_size as usize)])
.unwrap();
self.data.write_all(&buffer[0..read]).unwrap();
remaining_size -= read as u64;
}
self.current_offset += file_info.local_header.size() as u64 + file_size;
self.files.push(file_info);
}
/// Finish the zip file by writing the central directory.
pub fn write_central_directory(&mut self) {
for file_info in &self.files {
file_info.header.serialize(&mut self.data).unwrap();
}
// TODO: zip64
EndCentralDirectory {
disk_number: 0,
disk_number_of_central_directory_start: 0,
number_of_entries_in_central_directory_on_disk: self.files.len() as u16,
number_of_entries_in_central_directory: self.files.len() as u16,
size_central_directory: self
.files
.iter()
.map(|file| file.local_header.size() as u32 + file.get_compressed_size() as u32)
.sum(),
offset_central_directory: self.current_offset as u32,
comment: vec![],
}
.serialize(&mut self.data)
.unwrap();
}
}