Skip to content

Commit 003039d

Browse files
authored
Merge pull request #679 from cgwalters/import-xattrs
tar: Propagate PAX extensions (including xattrs)
2 parents 05dd65f + e33340d commit 003039d

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ regex = "1.5.4"
4242
rustix = { version = "0.38", features = ["fs", "process"] }
4343
serde = { features = ["derive"], version = "1.0.125" }
4444
serde_json = "1.0.64"
45-
tar = "0.4.38"
45+
tar = "0.4.43"
4646
tempfile = "3.2.0"
4747
terminal_size = "0.3"
4848
tokio = { features = ["io-std", "time", "process", "rt", "net"], version = ">= 1.13.0" }

lib/src/tar/write.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const EXCLUDED_TOPLEVEL_PATHS: &[&str] = &["run", "tmp", "proc", "sys", "dev"];
3535
/// Copy a tar entry to a new tar archive, optionally using a different filesystem path.
3636
#[context("Copying entry")]
3737
pub(crate) fn copy_entry(
38-
entry: tar::Entry<impl std::io::Read>,
38+
mut entry: tar::Entry<impl std::io::Read>,
3939
dest: &mut tar::Builder<impl std::io::Write>,
4040
path: Option<&Path>,
4141
) -> Result<()> {
@@ -46,6 +46,15 @@ pub(crate) fn copy_entry(
4646
(*entry.path()?).to_owned()
4747
};
4848
let mut header = entry.header().clone();
49+
if let Some(headers) = entry.pax_extensions()? {
50+
let extensions = headers
51+
.map(|ext| {
52+
let ext = ext?;
53+
Ok((ext.key()?, ext.value_bytes()))
54+
})
55+
.collect::<Result<Vec<_>>>()?;
56+
dest.append_pax_extensions(extensions.as_slice().iter().copied())?;
57+
}
4958

5059
// Need to use the entry.link_name() not the header.link_name()
5160
// api as the header api does not handle long paths:

lib/tests/it/main.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,68 @@ async fn test_old_code_parses_new_export() -> Result<()> {
16771677
Ok(())
16781678
}
16791679

1680+
/// Test for https://github.com/ostreedev/ostree-rs-ext/issues/655
1681+
#[tokio::test]
1682+
async fn test_container_xattr() -> Result<()> {
1683+
let fixture = Fixture::new_v1()?;
1684+
let sh = fixture.new_shell()?;
1685+
let baseimg = &fixture.export_container().await?.0;
1686+
let basepath = &match baseimg.transport {
1687+
Transport::OciDir => fixture.path.join(baseimg.name.as_str()),
1688+
_ => unreachable!(),
1689+
};
1690+
1691+
// Build a derived image
1692+
let derived_path = &fixture.path.join("derived.oci");
1693+
oci_clone(basepath, derived_path).await?;
1694+
ostree_ext::integrationtest::generate_derived_oci_from_tar(
1695+
derived_path,
1696+
|w| {
1697+
let mut tar = tar::Builder::new(w);
1698+
let mut h = tar::Header::new_gnu();
1699+
h.set_entry_type(tar::EntryType::Regular);
1700+
h.set_uid(0);
1701+
h.set_gid(0);
1702+
h.set_mode(0o644);
1703+
h.set_mtime(0);
1704+
let data = b"hello";
1705+
h.set_size(data.len() as u64);
1706+
tar.append_pax_extensions([("SCHILY.xattr.user.foo", b"bar".as_slice())])
1707+
.unwrap();
1708+
tar.append_data(&mut h, "usr/bin/testxattr", std::io::Cursor::new(data))
1709+
.unwrap();
1710+
Ok::<_, anyhow::Error>(())
1711+
},
1712+
None,
1713+
None,
1714+
)?;
1715+
let derived_ref = &OstreeImageReference {
1716+
sigverify: SignatureSource::ContainerPolicyAllowInsecure,
1717+
imgref: ImageReference {
1718+
transport: Transport::OciDir,
1719+
name: derived_path.to_string(),
1720+
},
1721+
};
1722+
let mut imp =
1723+
store::ImageImporter::new(fixture.destrepo(), derived_ref, Default::default()).await?;
1724+
let prep = match imp.prepare().await.context("Init prep derived")? {
1725+
store::PrepareResult::AlreadyPresent(_) => panic!("should not be already imported"),
1726+
store::PrepareResult::Ready(r) => r,
1727+
};
1728+
let import = imp.import(prep).await.unwrap();
1729+
let merge_commit = import.merge_commit;
1730+
1731+
// Yeah we just scrape the output of ostree because it's easy
1732+
let out = cmd!(
1733+
sh,
1734+
"ostree --repo=dest/repo ls -X {merge_commit} /usr/bin/testxattr"
1735+
)
1736+
.read()?;
1737+
assert!(out.contains("'user.foo', [byte 0x62, 0x61, 0x72]"));
1738+
1739+
Ok(())
1740+
}
1741+
16801742
#[ignore]
16811743
#[tokio::test]
16821744
// Verify that we can push and pull to a registry, not just oci-archive:.

0 commit comments

Comments
 (0)