Skip to content

Commit

Permalink
Merge pull request #2 from elbe0046/elbe0046-attempt-2
Browse files Browse the repository at this point in the history
Fix handling contents added after header creation
  • Loading branch information
elbe0046 committed Mar 7, 2022
2 parents fec0c53 + 378fdb2 commit c8662e7
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 42 deletions.
18 changes: 7 additions & 11 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,8 @@ impl<W: Write> Builder<W> {
/// header will be modified.
///
/// Then it will append the header, followed by contents of the stream
/// specified by `data`, with the `size` field of `header` enforced as an
/// upper limit. To produce a valid archive the `size` field of `header`
/// must be less than or equal to the length of the stream that's being
/// specified by `data`. To produce a valid archive the `size` field of
/// `header` must be the same as the length of the stream that's being
/// written.
///
/// Note that this will not attempt to seek the archive to a valid position,
Expand Down Expand Up @@ -407,13 +406,9 @@ impl<W: Write> Builder<W> {
}
}

fn append(mut dst: &mut dyn Write, header: &Header, data: &mut dyn Read) -> io::Result<()> {
fn append(mut dst: &mut dyn Write, header: &Header, mut data: &mut dyn Read) -> io::Result<()> {
dst.write_all(header.as_bytes())?;
// Guards against there being more data than the header indicates in the case where contents
// have been appended to the file since the header was created.
let size = header.size()?;
let mut limited = data.take(size);
let len = io::copy(&mut limited, &mut dst)?;
let len = io::copy(&mut data, &mut dst)?;

// Pad with zeros if necessary.
let buf = [0; 512];
Expand Down Expand Up @@ -449,7 +444,8 @@ fn append_path_with_name(
};
let ar_name = name.unwrap_or(path);
if stat.is_file() {
append_fs(dst, ar_name, &stat, &mut fs::File::open(path)?, mode, None)
let file = fs::File::open(path)?;
append_fs(dst, ar_name, &stat, &mut file.take(stat.len()), mode, None)
} else if stat.is_dir() {
append_fs(dst, ar_name, &stat, &mut io::empty(), mode, None)
} else if stat.file_type().is_symlink() {
Expand Down Expand Up @@ -525,7 +521,7 @@ fn append_file(
mode: HeaderMode,
) -> io::Result<()> {
let stat = file.metadata()?;
append_fs(dst, path, &stat, file, mode, None)
append_fs(dst, path, &stat, &mut file.take(stat.len()), mode, None)
}

fn append_dir(
Expand Down
32 changes: 1 addition & 31 deletions tests/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1279,12 +1279,10 @@ fn append_long_multibyte() {
let mut x = tar::Builder::new(Vec::new());
let mut name = String::new();
let data: &[u8] = &[];
let mut header = Header::new_gnu();
header.set_size(data.len() as u64);
for _ in 0..512 {
name.push('a');
name.push('𑢮');
x.append_data(&mut header, &name, data).unwrap();
x.append_data(&mut Header::new_gnu(), &name, data).unwrap();
name.pop();
}
}
Expand Down Expand Up @@ -1387,31 +1385,3 @@ fn header_size_overflow() {
err
);
}

#[test]
fn file_contents_appended_after_header_creation() {
let mut data = String::from("Hello");

let mut header = Header::new_gnu();
header.set_size(data.len() as u64);
header.set_cksum();

// Additional data is appended after header creation
data.push_str(", World!");

let mut ar = Builder::new(Vec::new());
t!(ar.append_data(&mut header, "test2", data.as_bytes()));

let raw = t!(ar.into_inner());
let mut ar = Archive::new(Cursor::new(raw));
let mut entries = t!(ar.entries());
let entry = t!(entries.next().unwrap());
let offset = entry.raw_file_position();
let mut raw = ar.into_inner();

let mut s = String::new();
raw.set_position(offset);
t!(raw.read_to_string(&mut s));
let s = s.trim_end_matches(char::from(0));
assert_eq!(s, "Hello");
}

0 comments on commit c8662e7

Please sign in to comment.