chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

2024
vendor/tar/tests/all.rs vendored Normal file

File diff suppressed because it is too large Load Diff

466
vendor/tar/tests/entry.rs vendored Normal file
View File

@@ -0,0 +1,466 @@
extern crate tar;
extern crate tempfile;
use std::fs::create_dir;
use std::fs::File;
use std::io::Read;
use tempfile::Builder;
#[test]
fn absolute_symlink() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name("/bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
ar.unpack(td.path()).unwrap();
td.path().join("foo").symlink_metadata().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let mut entries = ar.entries().unwrap();
let entry = entries.next().unwrap().unwrap();
assert_eq!(&*entry.link_name_bytes().unwrap(), b"/bar");
}
#[test]
fn absolute_hardlink() {
let td = Builder::new().prefix("tar").tempdir().unwrap();
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Link);
header.set_path("bar").unwrap();
// This absolute path under tempdir will be created at unpack time
header.set_link_name(td.path().join("foo")).unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
ar.unpack(td.path()).unwrap();
td.path().join("foo").metadata().unwrap();
td.path().join("bar").metadata().unwrap();
}
#[test]
fn relative_hardlink() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Link);
header.set_path("bar").unwrap();
header.set_link_name("foo").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
ar.unpack(td.path()).unwrap();
td.path().join("foo").metadata().unwrap();
td.path().join("bar").metadata().unwrap();
}
#[test]
fn absolute_link_deref_error() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name("/").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo/bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
assert!(ar.unpack(td.path()).is_err());
td.path().join("foo").symlink_metadata().unwrap();
assert!(File::open(td.path().join("foo").join("bar")).is_err());
}
#[test]
fn relative_link_deref_error() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name("../../../../").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo/bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
assert!(ar.unpack(td.path()).is_err());
td.path().join("foo").symlink_metadata().unwrap();
assert!(File::open(td.path().join("foo").join("bar")).is_err());
}
#[test]
#[cfg(unix)]
fn directory_maintains_permissions() {
use ::std::os::unix::fs::PermissionsExt;
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Directory);
header.set_path("foo").unwrap();
header.set_mode(0o777);
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
ar.unpack(td.path()).unwrap();
let f = File::open(td.path().join("foo")).unwrap();
let md = f.metadata().unwrap();
assert!(md.is_dir());
assert_eq!(md.permissions().mode(), 0o40777);
}
#[test]
#[cfg(unix)]
fn set_entry_mask() {
use ::std::os::unix::fs::PermissionsExt;
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo").unwrap();
header.set_mode(0o777);
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
let foo_path = td.path().join("foo");
let mut entries = ar.entries().unwrap();
let mut foo = entries.next().unwrap().unwrap();
foo.set_mask(0o027);
foo.unpack(&foo_path).unwrap();
let f = File::open(foo_path).unwrap();
let md = f.metadata().unwrap();
assert!(md.is_file());
assert_eq!(md.permissions().mode(), 0o100750);
}
#[test]
#[cfg(not(windows))] // dangling symlinks have weird permissions
fn modify_link_just_created() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name("bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("bar/foo").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo/bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
ar.unpack(td.path()).unwrap();
File::open(td.path().join("bar/foo")).unwrap();
File::open(td.path().join("bar/bar")).unwrap();
File::open(td.path().join("foo/foo")).unwrap();
File::open(td.path().join("foo/bar")).unwrap();
}
#[test]
#[cfg(not(windows))] // dangling symlinks have weird permissions
fn modify_outside_with_relative_symlink() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("symlink").unwrap();
header.set_link_name("..").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("symlink/foo/bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
let tar_dir = td.path().join("tar");
create_dir(&tar_dir).unwrap();
assert!(ar.unpack(tar_dir).is_err());
assert!(!td.path().join("foo").exists());
}
#[test]
fn parent_paths_error() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name("..").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo/bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
assert!(ar.unpack(td.path()).is_err());
td.path().join("foo").symlink_metadata().unwrap();
assert!(File::open(td.path().join("foo").join("bar")).is_err());
}
#[test]
#[cfg(unix)]
fn good_parent_paths_ok() {
use std::path::PathBuf;
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path(PathBuf::from("foo").join("bar")).unwrap();
header
.set_link_name(PathBuf::from("..").join("bar"))
.unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("bar").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
ar.unpack(td.path()).unwrap();
td.path().join("foo").join("bar").read_link().unwrap();
let dst = td.path().join("foo").join("bar").canonicalize().unwrap();
File::open(dst).unwrap();
}
#[test]
fn modify_hard_link_just_created() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Link);
header.set_path("foo").unwrap();
header.set_link_name("../test").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(1);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo").unwrap();
header.set_cksum();
ar.append(&header, &b"x"[..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
let test = td.path().join("test");
File::create(&test).unwrap();
let dir = td.path().join("dir");
assert!(ar.unpack(&dir).is_err());
let mut contents = Vec::new();
File::open(&test)
.unwrap()
.read_to_end(&mut contents)
.unwrap();
assert_eq!(contents.len(), 0);
}
#[test]
fn modify_symlink_just_created() {
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name("../test").unwrap();
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(1);
header.set_entry_type(tar::EntryType::Regular);
header.set_path("foo").unwrap();
header.set_cksum();
ar.append(&header, &b"x"[..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let td = Builder::new().prefix("tar").tempdir().unwrap();
let test = td.path().join("test");
File::create(&test).unwrap();
let dir = td.path().join("dir");
ar.unpack(&dir).unwrap();
let mut contents = Vec::new();
File::open(&test)
.unwrap()
.read_to_end(&mut contents)
.unwrap();
assert_eq!(contents.len(), 0);
}
/// Test that unpacking a tarball with a symlink followed by a directory entry
/// with the same name does not allow modifying permissions of arbitrary directories
/// outside the extraction path.
#[test]
#[cfg(unix)]
fn symlink_dir_collision_does_not_modify_external_dir_permissions() {
use ::std::fs;
use ::std::os::unix::fs::PermissionsExt;
let td = Builder::new().prefix("tar").tempdir().unwrap();
let target_dir = td.path().join("target-dir");
fs::create_dir(&target_dir).unwrap();
fs::set_permissions(&target_dir, fs::Permissions::from_mode(0o700)).unwrap();
let before_mode = fs::metadata(&target_dir).unwrap().permissions().mode() & 0o7777;
assert_eq!(before_mode, 0o700);
let extract_dir = td.path().join("extract-dir");
fs::create_dir(&extract_dir).unwrap();
let mut ar = tar::Builder::new(Vec::new());
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
header.set_path("foo").unwrap();
header.set_link_name(&target_dir).unwrap();
header.set_mode(0o777);
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Directory);
header.set_path("foo").unwrap();
header.set_mode(0o777);
header.set_cksum();
ar.append(&header, &[][..]).unwrap();
let bytes = ar.into_inner().unwrap();
let mut ar = tar::Archive::new(&bytes[..]);
let result = ar.unpack(&extract_dir);
assert!(result.is_err());
let symlink_path = extract_dir.join("foo");
assert!(symlink_path
.symlink_metadata()
.unwrap()
.file_type()
.is_symlink());
let after_mode = fs::metadata(&target_dir).unwrap().permissions().mode() & 0o7777;
assert_eq!(after_mode, 0o700);
}

256
vendor/tar/tests/header/mod.rs vendored Normal file
View File

@@ -0,0 +1,256 @@
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::Path;
use std::{mem, thread, time};
use tempfile::Builder;
use tar::{GnuHeader, Header, HeaderMode};
#[test]
fn default_gnu() {
let mut h = Header::new_gnu();
assert!(h.as_gnu().is_some());
assert!(h.as_gnu_mut().is_some());
assert!(h.as_ustar().is_none());
assert!(h.as_ustar_mut().is_none());
}
#[test]
fn goto_old() {
let mut h = Header::new_old();
assert!(h.as_gnu().is_none());
assert!(h.as_gnu_mut().is_none());
assert!(h.as_ustar().is_none());
assert!(h.as_ustar_mut().is_none());
}
#[test]
fn goto_ustar() {
let mut h = Header::new_ustar();
assert!(h.as_gnu().is_none());
assert!(h.as_gnu_mut().is_none());
assert!(h.as_ustar().is_some());
assert!(h.as_ustar_mut().is_some());
}
#[test]
fn link_name() {
let mut h = Header::new_gnu();
h.set_link_name("foo").unwrap();
assert_eq!(h.link_name().unwrap().unwrap().to_str(), Some("foo"));
h.set_link_name("../foo").unwrap();
assert_eq!(h.link_name().unwrap().unwrap().to_str(), Some("../foo"));
h.set_link_name("foo/bar").unwrap();
assert_eq!(h.link_name().unwrap().unwrap().to_str(), Some("foo/bar"));
h.set_link_name("foo\\ba").unwrap();
if cfg!(windows) {
assert_eq!(h.link_name().unwrap().unwrap().to_str(), Some("foo/ba"));
} else {
assert_eq!(h.link_name().unwrap().unwrap().to_str(), Some("foo\\ba"));
}
let name = "foo\\bar\0";
for (slot, val) in h.as_old_mut().linkname.iter_mut().zip(name.as_bytes()) {
*slot = *val;
}
assert_eq!(h.link_name().unwrap().unwrap().to_str(), Some("foo\\bar"));
assert!(h.set_link_name("\0").is_err());
}
#[test]
fn mtime() {
let h = Header::new_gnu();
assert_eq!(h.mtime().unwrap(), 0);
let h = Header::new_ustar();
assert_eq!(h.mtime().unwrap(), 0);
let h = Header::new_old();
assert_eq!(h.mtime().unwrap(), 0);
}
#[test]
fn user_and_group_name() {
let mut h = Header::new_gnu();
h.set_username("foo").unwrap();
h.set_groupname("bar").unwrap();
assert_eq!(h.username().unwrap(), Some("foo"));
assert_eq!(h.groupname().unwrap(), Some("bar"));
h = Header::new_ustar();
h.set_username("foo").unwrap();
h.set_groupname("bar").unwrap();
assert_eq!(h.username().unwrap(), Some("foo"));
assert_eq!(h.groupname().unwrap(), Some("bar"));
h = Header::new_old();
assert_eq!(h.username().unwrap(), None);
assert_eq!(h.groupname().unwrap(), None);
assert!(h.set_username("foo").is_err());
assert!(h.set_groupname("foo").is_err());
}
#[test]
fn dev_major_minor() {
let mut h = Header::new_gnu();
h.set_device_major(1).unwrap();
h.set_device_minor(2).unwrap();
assert_eq!(h.device_major().unwrap(), Some(1));
assert_eq!(h.device_minor().unwrap(), Some(2));
h = Header::new_ustar();
h.set_device_major(1).unwrap();
h.set_device_minor(2).unwrap();
assert_eq!(h.device_major().unwrap(), Some(1));
assert_eq!(h.device_minor().unwrap(), Some(2));
h.as_ustar_mut().unwrap().dev_minor[0] = 0x7f;
h.as_ustar_mut().unwrap().dev_major[0] = 0x7f;
assert!(h.device_major().is_err());
assert!(h.device_minor().is_err());
h.as_ustar_mut().unwrap().dev_minor[0] = b'g';
h.as_ustar_mut().unwrap().dev_major[0] = b'h';
assert!(h.device_major().is_err());
assert!(h.device_minor().is_err());
h = Header::new_old();
assert_eq!(h.device_major().unwrap(), None);
assert_eq!(h.device_minor().unwrap(), None);
assert!(h.set_device_major(1).is_err());
assert!(h.set_device_minor(1).is_err());
}
#[test]
fn set_path() {
let mut h = Header::new_gnu();
h.set_path("foo").unwrap();
assert_eq!(h.path().unwrap().to_str(), Some("foo"));
h.set_path("foo/").unwrap();
assert_eq!(h.path().unwrap().to_str(), Some("foo/"));
h.set_path("foo/bar").unwrap();
assert_eq!(h.path().unwrap().to_str(), Some("foo/bar"));
h.set_path("foo\\bar").unwrap();
if cfg!(windows) {
assert_eq!(h.path().unwrap().to_str(), Some("foo/bar"));
} else {
assert_eq!(h.path().unwrap().to_str(), Some("foo\\bar"));
}
// set_path documentation explicitly states it removes any ".", signifying the
// current directory, from the path. This test ensures that documented
// behavior occurs
h.set_path("./control").unwrap();
assert_eq!(h.path().unwrap().to_str(), Some("control"));
let long_name = "foo".repeat(100);
let medium1 = "foo".repeat(52);
let medium2 = "fo/".repeat(52);
assert!(h.set_path(&long_name).is_err());
assert!(h.set_path(&medium1).is_err());
assert!(h.set_path(&medium2).is_err());
assert!(h.set_path("\0").is_err());
assert!(h.set_path("..").is_err());
assert!(h.set_path("foo/..").is_err());
assert!(h.set_path("foo/../bar").is_err());
h = Header::new_ustar();
h.set_path("foo").unwrap();
assert_eq!(h.path().unwrap().to_str(), Some("foo"));
assert!(h.set_path(&long_name).is_err());
assert!(h.set_path(&medium1).is_err());
h.set_path(&medium2).unwrap();
assert_eq!(h.path().unwrap().to_str(), Some(&medium2[..]));
}
#[test]
fn set_ustar_path_hard() {
let mut h = Header::new_ustar();
let p = Path::new("a").join(vec!["a"; 100].join(""));
h.set_path(&p).unwrap();
assert_eq!(h.path().unwrap(), p);
}
#[test]
fn set_metadata_deterministic() {
let td = Builder::new().prefix("tar-rs").tempdir().unwrap();
let tmppath = td.path().join("tmpfile");
fn mk_header(path: &Path, readonly: bool) -> Result<Header, io::Error> {
let mut file = File::create(path).unwrap();
file.write_all(b"c").unwrap();
let mut perms = file.metadata().unwrap().permissions();
perms.set_readonly(readonly);
fs::set_permissions(path, perms).unwrap();
let mut h = Header::new_ustar();
h.set_metadata_in_mode(&path.metadata().unwrap(), HeaderMode::Deterministic);
Ok(h)
}
// Create "the same" File twice in a row, one second apart, with differing readonly values.
let one = mk_header(tmppath.as_path(), false).unwrap();
thread::sleep(time::Duration::from_millis(1050));
let two = mk_header(tmppath.as_path(), true).unwrap();
// Always expected to match.
assert_eq!(one.size().unwrap(), two.size().unwrap());
assert_eq!(one.path().unwrap(), two.path().unwrap());
assert_eq!(one.mode().unwrap(), two.mode().unwrap());
// Would not match without `Deterministic`.
assert_eq!(one.mtime().unwrap(), two.mtime().unwrap());
assert_eq!(one.mtime().unwrap(), 1153704088);
// TODO: No great way to validate that these would not be filled, but
// check them anyway.
assert_eq!(one.uid().unwrap(), two.uid().unwrap());
assert_eq!(one.gid().unwrap(), two.gid().unwrap());
}
#[test]
fn extended_numeric_format() {
let mut h: GnuHeader = unsafe { mem::zeroed() };
h.as_header_mut().set_size(42);
assert_eq!(h.size, [48, 48, 48, 48, 48, 48, 48, 48, 48, 53, 50, 0]);
h.as_header_mut().set_size(8589934593);
assert_eq!(h.size, [0x80, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0, 1]);
h.as_header_mut().set_size(44);
assert_eq!(h.size, [48, 48, 48, 48, 48, 48, 48, 48, 48, 53, 52, 0]);
h.size = [0x80, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0, 0];
assert_eq!(h.as_header().entry_size().unwrap(), 0x0200000000);
h.size = [48, 48, 48, 48, 48, 48, 48, 48, 48, 53, 51, 0];
assert_eq!(h.as_header().entry_size().unwrap(), 43);
h.as_header_mut().set_gid(42);
assert_eq!(h.gid, [48, 48, 48, 48, 48, 53, 50, 0]);
assert_eq!(h.as_header().gid().unwrap(), 42);
h.as_header_mut().set_gid(0x7fffffffffffffff);
assert_eq!(h.gid, [0xff; 8]);
assert_eq!(h.as_header().gid().unwrap(), 0x7fffffffffffffff);
h.uid = [0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78];
assert_eq!(h.as_header().uid().unwrap(), 0x12345678);
h.mtime = [
0x80, 0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
];
assert_eq!(h.as_header().mtime().unwrap(), 0x0123456789abcdef);
h.realsize = [0x80, 0, 0, 0, 0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde];
assert_eq!(h.real_size().unwrap(), 0x00123456789abcde);
h.sparse[0].offset = [0x80, 0, 0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd];
assert_eq!(h.sparse[0].offset().unwrap(), 0x000123456789abcd);
h.sparse[0].numbytes = [0x80, 0, 0, 0, 0, 0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc];
assert_eq!(h.sparse[0].length().unwrap(), 0x0000123456789abc);
}
#[test]
fn byte_slice_conversion() {
let h = Header::new_gnu();
let b: &[u8] = h.as_bytes();
let b_conv: &[u8] = Header::from_byte_slice(h.as_bytes()).as_bytes();
assert_eq!(b, b_conv);
}