Skip to content

Commit

Permalink
tar/export: Add a repo/config with mode bare-split-xattrs
Browse files Browse the repository at this point in the history
Part of ostreedev/ostree#2499

Basically, ostree core should have first-class support for
reading and parsing this.  The primary motivation is to support
ostree-in-container better.

The real main wrinkle here is xattrs, as usual.  We can't rely on
being able to read/write xattrs inside a container.

For now, this will serve sufficient to *identify* this format,
but it will pave the way for ostree core to support read/write.

(Note that if we go to implement writes, a notable wrinkle is that
 garbage collection of the `xattrs` subdirectory will require
 another special handling pass)
  • Loading branch information
cgwalters committed Dec 17, 2021
1 parent 2d1805c commit 6d648da
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 15 deletions.
25 changes: 22 additions & 3 deletions lib/src/tar/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ const SYSROOT: &str = "sysroot";
// This way the default ostree -> sysroot/ostree symlink works.
const OSTREEDIR: &str = "sysroot/ostree";

/// The base repository configuration that identifies this is a tar export.
// See https://github.com/ostreedev/ostree/issues/2499
const REPO_CONFIG: &str = r#"[core]
repo_version=1
mode=bare-split-xattrs
"#;

/// A decently large buffer, as used by e.g. coreutils `cat`.
/// System calls are expensive.
const BUF_CAPACITY: usize = 131072;
Expand Down Expand Up @@ -94,8 +101,8 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
Ok(())
}

/// Write the initial directory structure.
fn write_initial_directories(&mut self) -> Result<()> {
/// Write the initial /sysroot/ostree/repo structure.
fn write_repo_structure(&mut self) -> Result<()> {
if self.wrote_initdirs {
return Ok(());
}
Expand Down Expand Up @@ -124,6 +131,18 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
// The special `repo/xattrs` directory used only in our tar serialization.
let path: Utf8PathBuf = format!("{}/repo/xattrs", OSTREEDIR).into();
self.append_default_dir(&path)?;
let mut h = tar::Header::new_gnu();
h.set_entry_type(tar::EntryType::Regular);
h.set_uid(0);
h.set_gid(0);
h.set_mode(0o644);
h.set_size(REPO_CONFIG.as_bytes().len() as u64);
self.out.append_data(
&mut h,
&format!("{}/repo/config", OSTREEDIR),
std::io::Cursor::new(REPO_CONFIG),
)?;

Ok(())
}

Expand Down Expand Up @@ -152,7 +171,7 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
self.append_dir(rootpath, metadata)?;

// Now, we create sysroot/ and everything under it
self.write_initial_directories()?;
self.write_repo_structure()?;

self.append(ostree::ObjectType::Commit, checksum, commit_v)?;
if let Some(commitmeta) = self
Expand Down
37 changes: 25 additions & 12 deletions lib/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,22 +253,35 @@ fn test_tar_export_structure() -> Result<()> {
assert_eq!(first.header().mode()?, libc::S_IFDIR | 0o755);
let next = entries.next().unwrap().unwrap();
assert_eq!(next.path().unwrap().as_os_str(), "sysroot");

let expected = vec![
(
"sysroot/ostree/repo/config",
tar::EntryType::Regular,
0o644,
),
("usr", tar::EntryType::Directory, libc::S_IFDIR | 0o755),
];
let mut entries = entries.map(|e| e.unwrap());

// Verify we're injecting directories, fixes the absence of `/tmp` in our
// images for example.
entries
.map(|e| e.unwrap())
.find(|entry| {
for (path, expected_type, expected_mode) in expected {
let mut found = false;
while let Some(entry) = entries.next() {
let header = entry.header();
let path = entry.path().unwrap();
if path.as_os_str() == "usr" {
assert_eq!(header.entry_type(), tar::EntryType::Directory);
assert_eq!(header.mode().unwrap(), libc::S_IFDIR | 0o755);
true
} else {
false
let entry_path = entry.path().unwrap();
if path == entry_path.as_os_str() {
assert_eq!(header.entry_type(), expected_type);
assert_eq!(header.mode().unwrap(), expected_mode);
found = true;
break;
}
})
.unwrap();
}
if !found {
panic!("Failed to find entry: {}", path);
}
}
Ok(())
}

Expand Down

0 comments on commit 6d648da

Please sign in to comment.