Skip to content

Commit

Permalink
oci: make create-image actually create the image
Browse files Browse the repository at this point in the history
Also add a new create-dumpfile which does what create-image used to do.
This is really useful for debugging purposes.

Also adjust the hardlink output format to match the stricter validation
requirements of new versions of mkcomposefs.

Closes #6
  • Loading branch information
allisonkarlitskaya committed Oct 14, 2024
1 parent 15045ed commit 09c5167
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 20 deletions.
12 changes: 10 additions & 2 deletions src/bin/cfsctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ enum OciCommand {
/// the name of the stream
name: String,
},
CreateDumpfile {
layers: Vec<String>,
},
CreateImage {
name: String,
layers: Vec<String>,
},
}
Expand Down Expand Up @@ -120,8 +124,12 @@ fn main() -> Result<()> {
OciCommand::LsLayer { name } => {
oci::ls_layer(&repo, &name)?;
},
OciCommand::CreateImage { layers } => {
oci::image::create_image(&repo, &layers)?;
OciCommand::CreateDumpfile { layers } => {
oci::image::create_dumpfile(&repo, &layers)?;
},
OciCommand::CreateImage { name, layers } => {
let image_id = oci::image::create_image(&repo, &name, &layers)?;
println!("{}", hex::encode(image_id));
},
}
Command::Mount { name, mountpoint } => {
Expand Down
21 changes: 11 additions & 10 deletions src/dumpfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,28 +127,29 @@ fn write_entry(
}

pub fn write_directory(writer: &mut impl fmt::Write, path: &Path, stat: &Stat, nlink: usize) -> fmt::Result {
write_entry(writer, path, stat, FileType::Directory, 0, nlink, 0, &"", &[], None)
write_entry(writer, path, stat, FileType::Directory, 0, nlink, 0, "", &[], None)
}

pub fn write_leaf(writer: &mut impl fmt::Write, path: &Path, stat: &Stat, content: &LeafContent, nlink: usize) -> fmt::Result {
match content {
LeafContent::InlineFile(ref data) => write_entry(
writer, path, stat, FileType::RegularFile, data.len() as u64, nlink, 0, &"", data, None
writer, path, stat, FileType::RegularFile, data.len() as u64, nlink, 0, "", data, None
),
LeafContent::ExternalFile(id, size) => write_entry(
writer, path, stat, FileType::RegularFile, *size, nlink, 0, &"", &[], Some(id)
writer, path, stat, FileType::RegularFile, *size, nlink, 0,
format!("{:02x}/{}", id[0], hex::encode(&id[1..])), &[], Some(id)
),
LeafContent::BlockDevice(rdev) => write_entry(
writer, path, stat, FileType::BlockDevice, 0, nlink, *rdev, &"", &[], None
writer, path, stat, FileType::BlockDevice, 0, nlink, *rdev, "", &[], None
),
LeafContent::CharacterDevice(rdev) => write_entry(
writer, path, stat, FileType::CharacterDevice, 0, nlink, *rdev, &"", &[], None
writer, path, stat, FileType::CharacterDevice, 0, nlink, *rdev, "", &[], None
),
LeafContent::Fifo => write_entry(
writer, path, stat, FileType::Fifo, 0, nlink, 0, &"", &[], None
writer, path, stat, FileType::Fifo, 0, nlink, 0, "", &[], None
),
LeafContent::Socket => write_entry(
writer, path, stat, FileType::Socket, 0, nlink, 0, &"", &[], None
writer, path, stat, FileType::Socket, 0, nlink, 0, "", &[], None
),
LeafContent::Symlink(ref target) => write_entry(
writer, path, stat, FileType::Symlink, target.as_bytes().len() as u64, nlink, 0, target, &[], None
Expand All @@ -158,9 +159,9 @@ pub fn write_leaf(writer: &mut impl fmt::Write, path: &Path, stat: &Stat, conten

pub fn write_hardlink(writer: &mut impl fmt::Write, path: &Path, target: &OsStr) -> fmt::Result {
write_escaped(writer, path.as_os_str().as_bytes())?;
write!(writer, " - @0 - - - - - ")?;
write!(writer, " 0 @120000 - - - - 0.0 ")?;
write_escaped(writer, target.as_bytes())?;
writeln!(writer, " - -")?;
write!(writer, " - -")?;
Ok(())
}

Expand Down Expand Up @@ -226,5 +227,5 @@ impl<'a, W: Write> DumpfileWriter<'a, W> {
}

pub fn write_dumpfile<W: Write>(writer: &mut W, fs: &FileSystem) -> Result<()> {
Ok(DumpfileWriter::new(writer).write_dir(Path::new("/"), &fs.root)?)
DumpfileWriter::new(writer).write_dir(Path::new("/"), &fs.root)
}
47 changes: 45 additions & 2 deletions src/oci/image.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use std::{
ffi::OsStr,
io::Read,
os::unix::ffi::OsStrExt,
process::{
Command,
Stdio
},
};

use anyhow::{
Expand All @@ -9,6 +14,7 @@ use anyhow::{
};
use crate::{
dumpfile::write_dumpfile,
fsverity::Sha256HashValue,
image::{
FileSystem,
Leaf,
Expand Down Expand Up @@ -50,7 +56,7 @@ pub fn process_entry(filesystem: &mut FileSystem, entry: oci::tar::TarEntry) ->
Ok(())
}

pub fn create_image(repo: &Repository, layers: &Vec<String>) -> Result<()> {
pub fn compose_filesystem(repo: &Repository, layers: &[String]) -> Result<FileSystem> {
let mut filesystem = FileSystem::new();

for layer in layers {
Expand All @@ -61,8 +67,45 @@ pub fn create_image(repo: &Repository, layers: &Vec<String>) -> Result<()> {
}
}

Ok(filesystem)
}

pub fn create_dumpfile(repo: &Repository, layers: &[String]) -> Result<()> {
let filesystem = compose_filesystem(repo, layers)?;
let mut stdout = std::io::stdout();
write_dumpfile(&mut stdout, &filesystem)?;

Ok(())
}

pub fn create_image(repo: &Repository, name: &str, layers: &Vec<String>) -> Result<Sha256HashValue> {
let mut filesystem = FileSystem::new();

for layer in layers {
let mut split_stream = repo.open_stream(layer)?;
let mut reader = SplitStreamReader::new(&mut split_stream);
while let Some(entry) = oci::tar::get_entry(&mut reader)? {
process_entry(&mut filesystem, entry)?;
}
}

let mut mkcomposefs = Command::new("mkcomposefs")
.args(["--from-file", "-", "-"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;

let mut stdin = mkcomposefs.stdin.take().unwrap();
write_dumpfile(&mut stdin, &filesystem)?;
drop(stdin);

let mut stdout = mkcomposefs.stdout.take().unwrap();
let mut image = vec![];
stdout.read_to_end(&mut image)?;
drop(stdout);

if !mkcomposefs.wait()?.success() {
bail!("mkcomposefs failed");
};

repo.write_image(name, &image)
}
11 changes: 8 additions & 3 deletions src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,17 @@ impl Repository {
Ok(())
}

/// this function is not safe for untrusted users
pub fn write_image(&self, name: &str, data: &[u8]) -> Result<Sha256HashValue> {
let object_id = self.ensure_object(data)?;
self.link_ref(name, "images", object_id)
}

/// this function is not safe for untrusted users
pub fn import_image<R: Read>(&self, name: &str, image: &mut R) -> Result<Sha256HashValue> {
let mut data = vec![];
image.read_to_end(&mut data)?;
let object_id = self.ensure_object(&data)?;
self.link_ref(name, "images", object_id)
self.write_image(name, &data)
}

pub fn mount(self, name: &str, mountpoint: &str) -> Result<()> {
Expand All @@ -305,8 +310,8 @@ impl Repository {
let category_path = format!("{}/{}", category, hex::encode(object_id));
let ref_path = format!("{}/refs/{}", category, name);

self.ensure_symlink(&category_path, &object_path)?;
self.symlink(&ref_path, &category_path)?;
self.symlink(&category_path, &object_path)?;
Ok(object_id)
}

Expand Down
6 changes: 3 additions & 3 deletions tests/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ fn test_layer() -> Result<()> {
}
assert_eq!(dump, "\
/file0 0 100700 1 0 0 0 0.0 - - -
/file4095 4095 100700 1 0 0 0 0.0 - - 5372beb83c78537c8970c8361e3254119fafdf1763854ecd57d3f0fe2da7c719
/file4096 4096 100700 1 0 0 0 0.0 - - babc284ee4ffe7f449377fbf6692715b43aec7bc39c094a95878904d34bac97e
/file4097 4097 100700 1 0 0 0 0.0 - - 093756e4ea9683329106d4a16982682ed182c14bf076463a9e7f97305cbac743
/file4095 4095 100700 1 0 0 0 0.0 53/72beb83c78537c8970c8361e3254119fafdf1763854ecd57d3f0fe2da7c719 - 5372beb83c78537c8970c8361e3254119fafdf1763854ecd57d3f0fe2da7c719
/file4096 4096 100700 1 0 0 0 0.0 ba/bc284ee4ffe7f449377fbf6692715b43aec7bc39c094a95878904d34bac97e - babc284ee4ffe7f449377fbf6692715b43aec7bc39c094a95878904d34bac97e
/file4097 4097 100700 1 0 0 0 0.0 09/3756e4ea9683329106d4a16982682ed182c14bf076463a9e7f97305cbac743 - 093756e4ea9683329106d4a16982682ed182c14bf076463a9e7f97305cbac743
");
Ok(())
}

0 comments on commit 09c5167

Please sign in to comment.