-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
read tar file by requested block #13
Comments
Not sure how to accomplish the Solution. And |
Crate |
What is wanted is to create an Creating an Here are the permutation of technical approaches I have tried:
Again, I tried many permutations of all of the prior. The closest I got was use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::cell::RefCell;
use std::ops::DerefMut;
use std::pin::Pin;
use ::copyless;
use ::tar::Archive;
use ::tar::Entries;
use ::tar::Entry;
std::thread_local! {
static MyArchive4: RefCell<Option<Box<Archive<File>>>> = {
eprintln!("thread_local! MyArchive4");
RefCell::new(None)
};
static MyEntry4: RefCell<Option<Box<Entry<'static, File>>>> = {
eprintln!("thread_local! MyEntry4");
RefCell::new(None)
};
static MyEntries4: RefCell<Option<Box<Entries<'static, File>>>> = {
eprintln!("thread_local! MyEntries4");
RefCell::new(None)
};
}
fn main() {
let args: Vec<String> = env::args().collect();
let filename = &args[1];
MyArchive4.with(|rca| {
let file: File = File::open(filename).unwrap();
unsafe {
// https://stackoverflow.com/a/59368947/471376
// forcibly allocate on the heap
let mut bx = <Box<Archive<File>> as copyless::BoxHelper<Archive<File>>>::alloc();
rca.borrow_mut().replace(
copyless::BoxAllocation::init(
bx,
Archive::<File>::new(file)
)
);
}
MyEntries4.with(|rces| {
unsafe {
let mut bx = <Box<Entries<'_, File>> as copyless::BoxHelper<Entries<'_, File>>>::alloc();
MyEntry4.with(|rce| {
let mut bx = <Box<Entry<'_, File>> as copyless::BoxHelper<Entry<'_, File>>>::alloc();
rce.borrow_mut().replace(
copyless::BoxAllocation::init(
bx,
rca.borrow_mut().as_mut().unwrap().entries().unwrap().nth(0).unwrap().unwrap()
)
);
});
}
});
});
} but this results in error
another approach that violated teh borrow checker use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::cell::RefCell;
use std::ops::DerefMut;
use std::pin::Pin;
use ::copyless;
use ::tar::Archive;
use ::tar::Entries;
use ::tar::Entry;
std::thread_local! {
static MyArchiveEntriesEntry8: RefCell<Option<Box<(Archive<File>, Entries<'static, File>, Entry<'static, File>)>>> = {
eprintln!("thread_local! MyArchiveEntriesEntry8");
RefCell::new(None)
};
}
fn main() {
let args: Vec<String> = env::args().collect();
let filename = &args[1];
MyArchiveEntriesEntry8.with(|rcae| {
let file: File = File::open(filename).unwrap();
let mut archive = Archive::new(file);
let mut entries = archive.entries().unwrap();
let mut entry = entries.nth(0).unwrap().unwrap();
rcae.borrow_mut().replace(Box::new((archive, entries, entry)));
});
} results in
Another permutation use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::cell::RefCell;
use std::ops::DerefMut;
use std::pin::Pin;
use ::copyless;
use ::tar::Archive;
use ::tar::Entries;
use ::tar::Entry;
std::thread_local! {
static MyArchive: RefCell<Option<Pin<Box<*mut Archive<File>>>>> = {
eprintln!("thread_local! MyArchive");
RefCell::new(None)
};
static MyEntry: RefCell<Option<Pin<Box<*mut Entry<'static, File>>>>> = {
eprintln!("thread_local! MyEntry");
RefCell::new(None)
};
static MyEntries: RefCell<Option<Pin<Box<*mut Entries<'static, File>>>>> = {
eprintln!("thread_local! MyEntries");
RefCell::new(None)
};
}
fn main() {
let args: Vec<String> = env::args().collect();
let filename = &args[1];
MyArchive.with(|rca| {
let file: File = File::open(filename).unwrap();
let mut archive = &mut Archive::new(file);
let mut parchive: Box<*mut Archive<File>> = Box::new(archive);
MyEntries.with(|rces| {
unsafe {
let mut es = parchive.deref_mut().as_mut().unwrap().entries().unwrap();
let mut entries: Box<*mut Entries<File>> = Box::new(&mut es);
MyEntry.with(|rce| {
let mut entry: Box<*mut tar::Entry<File>> = match es.nth(0) {
Some(Ok(ref mut e)) => {
eprintln!("nth(0) OK {:?}", e.header().path().unwrap());
Box::new(e)
}
Some(Err(e)) => {
panic!("{}", e);
}
None => {
panic!("None");
}
};
rce.borrow_mut().replace(Pin::new(entry));
});
rces.borrow_mut().replace(Pin::new(entries));
}
});
rca.borrow_mut().replace(Pin::new(parchive));
});
} This compiles and runs but |
Problem
An
.tar
file is entirely read duringBlockReader::read_block_FileTar
.This may cause problems for very large compressed files (the
s4
program will have the entire unarchived file in memory; it will use too much memory).This is due to design of the
tar
crate. The crate does not provide a method to storetar::Archive<File>
instance andtar::Entry<'a, R: 'a + Read>
instance due to inter-instance references and explicit lifetimes. (or is prohibitively complex; I made many attempts using various strategies involving references, lifetimes, pointers, etc.)A
tar::Entry
holds a reference to data within thetar::Archive<File>
. I found it impossible to store both related instances duringnew()
orread_block_FileTar()
and then later, during another call toread_block_FileTar()
, utilize the sametar::Entry
.A new
tar::Entry
could be created per call toread_block_FileTar()
. But then to read the requestedBlockOffset
, the entire.tar
file entry would have to re-read. This means reading an entire file entry within a.tar
file would be an O(n^2) algorithm.Solution
Read an
.tar
file per block request, as done for normal files.Meta Issue #182
Similar problem as Issue #12.
The text was updated successfully, but these errors were encountered: