-
Notifications
You must be signed in to change notification settings - Fork 15
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
Problems with parsing rust-ar generated archives after ranlib #10
Comments
Ar produced file:
rust-ar produced file:
|
Ping @mdsteele |
Thanks for the detailed writeup; sorry for the delayed response. When a filename within an archive file is longer than 16 characters, there are two prevailing formats for encoding it: the GNU format and the BSD format. Currently, Looking at your second comment, I can see that your I think the right solution here would be to give |
No problem. I won't need large filenames until rust-lang/rust#59564 is merged anyway.
What about passing in a reader when adding a file, instead of returning a writer. The readers can then be stored when producing a GNU archive and can be written all at once after all files have been added when the Builder is dropped. It can still immediately write them when a BSD archive is produced. |
I like this idea, but unfortunately in some cases it's not feasible to have all the readers in scope at once. For example, if you're reading files out of one archive and writing them into another, you have to drop the first reader out of scope before you can get the next one, so there's no way for the builder to be storing all those readers at once. |
:( Copying from one to another archive is very important for me. |
Maybe something like this. struct DelayedWritable(u64);
struct WriteDelayed(...);
impl<W: Write> Builder<W> {
fn new(W) -> Builder<W>;
fn write_delayed(self) -> Result<WriteDelayed<W>>; // new
fn append<'a, R: Read + 'a>(&'a mut self, &Header, R) -> Result<()>; // reader outlives self
fn append_path<P: AsRef<Path>>(&mut self, P) -> Result<()>; // unchanged
fn append_file(&'a mut self, Cow<'a, [u8]>, &mut File) -> Result<()>; // Cow name
/// When used you must call .write_delayed() and then .set_data for every append_delayed or there will be a panic.
fn append_delayed(&mut self, Header) -> DelayedWritable; // new
}
impl <W: Write> WriteDelayed<W> {
fn set_data<R: Read>(&mut self, DelayedWritable, R) -> Result<()>;
fn into_inner(self) -> Result<W>;
} It still stores a reader where possible, but gives also the option to provide the reader after all filenames are known. |
Oops didn't notice 1cfa68d :) |
Unfortunately I got:
when trying Repro: //! ```cargo
//! [dependencies]
//! ar = { git = "https://github.com/mdsteele/rust-ar.git" }
//! ```
use std::io::Read;
fn main() {
let filenames = vec![b"rust.metadata.bin".to_vec(), b"compiler_builtins-78891cf83a7d3547.dummy_name.rcgu.o".to_vec()];
let mut builder = ar::GnuBuilder::new(std::fs::File::create("test.a").expect("create"), filenames.clone());
for filename in filenames {
builder.append(&ar::Header::new(filename, 0), &mut (&[] as &[u8])).expect("add file");
}
std::mem::drop(builder);
// Remove this ranlib invocation and there is no problem.
assert!(
std::process::Command::new("ranlib")
.arg("test.a")
.status()
.expect("Couldn't run ranlib")
.success()
);
let mut archive = ar::Archive::new(std::fs::File::open("test.a").expect("open"));
while let Some(entry) = archive.next_entry() {
entry.unwrap();
}
}
|
Hmm. Could you try producing the same example archive with both |
ar:
rust-ar:
|
I am trying to fix this. |
I found the root problem: it an identifier doesn't have a size of a multiple of 2, then the name table doesn't have a multiple of 2 size either. PR #11 will fix this. |
Edit: change example to be clearer.
The text was updated successfully, but these errors were encountered: