Skip to content

Commit

Permalink
header: set entry_size() to 0 for hardlinks
Browse files Browse the repository at this point in the history
Fix the error: "numeric field was not a number: t 'Regard' when getting cksum for
'a text ...'. The error is caused by wrongly setting the `self.next`
position due to accounting harlinks size.

According to man 5 tar, the size of the hard-links should be set to 0.

size    Size of file, as octal number in ASCII.  For regular files	only,
        this indicates the	amount of data that follows the	header.	 In
        particular, this field was	ignored	by early tar implementations
        when extracting hardlinks.	 Modern	writers	should always store a
        zero length for hardlink entries.

But since the writer wasn't *modern*, the entry_size is 64700 which
causes miscalculation of the `self.next`.

[tar-rs/src/archive.rs:372] &entry.header() = UstarHeader {
    entry_size: 64700,
    size: 64700,
    path: "some/path",
    link_name: Some(
        "some/link",
    ),
    mode: 0o640,
    uid: 1058,
    gid: 1061,
    mtime: 1673424346,
    username: Some(
        "example",
    ),
    groupname: Some(
        "example",
    ),
    device_major: Some(
        9,
    ),
    device_minor: Some(
        2,
    ),
    cksum: 24700,
    cksum_valid: true,
}
[tar-rs/src/archive.rs:373] entry.header().entry_type() = Link

Closes: alexcrichton#313

Signed-off-by: Nikola Pajkovsky <nikola@enhance.com>
  • Loading branch information
Nikola Pajkovsky committed Mar 29, 2023
1 parent f4f439c commit bcf09e0
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/header.rs
Expand Up @@ -298,6 +298,9 @@ impl Header {
///
/// May return an error if the field is corrupted.
pub fn entry_size(&self) -> io::Result<u64> {
if self.entry_type().is_hard_link() {
return Ok(0);
}
num_field_wrapper_from(&self.as_old().size).map_err(|err| {
io::Error::new(
err.kind(),
Expand Down
27 changes: 20 additions & 7 deletions tests/header/mod.rs
@@ -1,12 +1,14 @@
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::Path;
use std::{iter, mem, thread, time};

use std::{
fs::{self, File},
io::{self, Write},
iter, mem,
path::Path,
thread, time,
};

use tar::{EntryType, GnuHeader, Header, HeaderMode};
use tempfile::Builder;

use tar::{GnuHeader, Header, HeaderMode};

#[test]
fn default_gnu() {
let mut h = Header::new_gnu();
Expand Down Expand Up @@ -244,3 +246,14 @@ fn byte_slice_conversion() {
let b_conv: &[u8] = Header::from_byte_slice(h.as_bytes()).as_bytes();
assert_eq!(b, b_conv);
}

#[test]
fn hardlink_entry_size() {
let mut h = Header::new_ustar();
let p = Path::new("a").join(&vec!["a"; 100].join(""));
h.set_entry_type(EntryType::Link);
t!(h.set_path(&p));
t!(h.set_link_name("foo"));
h.set_size(200);
assert_eq!(t!(h.entry_size()), 0);
}

0 comments on commit bcf09e0

Please sign in to comment.