Skip to content

Commit d3f5e8b

Browse files
src: make everything generic over FsVerityHashValue
Convert all of the many places that we've been using Sha256HashValue for fs-verity hashes to be generic over FsVerityHashValue instead. Work the changes out across the codebase. Due to some missing features in Rust, this change (while fairly mechnical) is also pretty large. See for example: - it's not possible to omit type parameters from the declaration of a function when they are irrelevant to the body of the function - rust-lang/rfcs#424 Signed-off-by: Allison Karlitskaya <[email protected]>
1 parent 0cebb1f commit d3f5e8b

14 files changed

+327
-244
lines changed

src/bin/cfsctl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn main() -> Result<()> {
111111

112112
let args = App::parse();
113113

114-
let repo = (if let Some(path) = args.repo {
114+
let repo: Repository<Sha256HashValue> = (if let Some(path) = args.repo {
115115
Repository::open_path(CWD, path)
116116
} else if args.system {
117117
Repository::open_system()
@@ -193,7 +193,7 @@ fn main() -> Result<()> {
193193
println!("{}", image_id.to_hex());
194194
}
195195
Command::CreateDumpfile { ref path } => {
196-
composefs::fs::create_dumpfile(path)?;
196+
composefs::fs::create_dumpfile::<Sha256HashValue>(path)?;
197197
}
198198
Command::Mount { name, mountpoint } => {
199199
repo.mount(&name, &mountpoint)?;

src/bin/composefs-setup-root.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn open_root_fs(path: &Path) -> Result<OwnedFd> {
167167
}
168168

169169
fn mount_composefs_image(sysroot: &OwnedFd, name: &str) -> Result<OwnedFd> {
170-
let repo = Repository::open_path(sysroot, "composefs")?;
170+
let repo = Repository::<Sha256HashValue>::open_path(sysroot, "composefs")?;
171171
let image = repo.open_image(name)?;
172172
composefs_fsmount(image, name, repo.object_dir()?).context("Failed to mount composefs image")
173173
}
@@ -200,11 +200,11 @@ fn mount_subdir(
200200
}
201201

202202
// Implementation
203-
fn parse_composefs_cmdline(cmdline: &[u8]) -> Result<Sha256HashValue> {
203+
fn parse_composefs_cmdline<H: FsVerityHashValue>(cmdline: &[u8]) -> Result<H> {
204204
// TODO?: officially we need to understand quoting with double-quotes...
205205
for part in cmdline.split(|c| c.is_ascii_whitespace()) {
206206
if let Some(digest) = part.strip_prefix(b"composefs=") {
207-
return Sha256HashValue::from_hex(digest).context("Parsing composefs=");
207+
return H::from_hex(digest).context("Parsing composefs=");
208208
}
209209
}
210210
bail!("Unable to find composefs= cmdline parameter");
@@ -236,7 +236,7 @@ fn setup_root(args: Args) -> Result<()> {
236236
Some(cmdline) => cmdline.as_bytes(),
237237
None => &std::fs::read("/proc/cmdline")?,
238238
};
239-
let image = parse_composefs_cmdline(cmdline)?.to_hex();
239+
let image = parse_composefs_cmdline::<Sha256HashValue>(cmdline)?.to_hex();
240240

241241
let new_root = match args.root_fs {
242242
Some(path) => open_root_fs(&path).context("Failed to clone specified root fs")?,
@@ -290,11 +290,12 @@ mod test {
290290
fn test_parse() {
291291
let failing = ["", "foo", "composefs", "composefs=foo"];
292292
for case in failing {
293-
assert!(parse_composefs_cmdline(case.as_bytes()).is_err());
293+
assert!(parse_composefs_cmdline::<Sha256HashValue>(case.as_bytes()).is_err());
294294
}
295295
let digest = "8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52";
296296
similar_asserts::assert_eq!(
297-
parse_composefs_cmdline(format!("composefs={digest}").as_bytes()).unwrap(),
297+
parse_composefs_cmdline::<Sha256HashValue>(format!("composefs={digest}").as_bytes())
298+
.unwrap(),
298299
Sha256HashValue::from_hex(digest).unwrap()
299300
);
300301
}

src/dumpfile.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ pub fn write_directory(
101101
)
102102
}
103103

104-
pub fn write_leaf(
104+
pub fn write_leaf<ObjectID: FsVerityHashValue>(
105105
writer: &mut impl fmt::Write,
106106
path: &Path,
107107
stat: &Stat,
108-
content: &LeafContent,
108+
content: &LeafContent<ObjectID>,
109109
nlink: usize,
110110
) -> fmt::Result {
111111
match content {
@@ -204,8 +204,8 @@ pub fn write_hardlink(writer: &mut impl fmt::Write, path: &Path, target: &OsStr)
204204
Ok(())
205205
}
206206

207-
struct DumpfileWriter<'a, W: Write> {
208-
hardlinks: HashMap<*const Leaf, OsString>,
207+
struct DumpfileWriter<'a, W: Write, ObjectID: FsVerityHashValue> {
208+
hardlinks: HashMap<*const Leaf<ObjectID>, OsString>,
209209
writer: &'a mut W,
210210
}
211211

@@ -215,15 +215,15 @@ fn writeln_fmt(writer: &mut impl Write, f: impl Fn(&mut String) -> fmt::Result)
215215
Ok(writeln!(writer, "{}", tmp)?)
216216
}
217217

218-
impl<'a, W: Write> DumpfileWriter<'a, W> {
218+
impl<'a, W: Write, ObjectID: FsVerityHashValue> DumpfileWriter<'a, W, ObjectID> {
219219
fn new(writer: &'a mut W) -> Self {
220220
Self {
221221
hardlinks: HashMap::new(),
222222
writer,
223223
}
224224
}
225225

226-
fn write_dir(&mut self, path: &mut PathBuf, dir: &Directory) -> Result<()> {
226+
fn write_dir(&mut self, path: &mut PathBuf, dir: &Directory<ObjectID>) -> Result<()> {
227227
// nlink is 2 + number of subdirectories
228228
// this is also true for the root dir since '..' is another self-ref
229229
let nlink = dir.inodes().fold(2, |count, inode| {
@@ -256,7 +256,7 @@ impl<'a, W: Write> DumpfileWriter<'a, W> {
256256
Ok(())
257257
}
258258

259-
fn write_leaf(&mut self, path: &Path, leaf: &Rc<Leaf>) -> Result<()> {
259+
fn write_leaf(&mut self, path: &Path, leaf: &Rc<Leaf<ObjectID>>) -> Result<()> {
260260
let nlink = Rc::strong_count(leaf);
261261

262262
if nlink > 1 {
@@ -276,7 +276,10 @@ impl<'a, W: Write> DumpfileWriter<'a, W> {
276276
}
277277
}
278278

279-
pub fn write_dumpfile<W: Write>(writer: &mut W, fs: &FileSystem) -> Result<()> {
279+
pub fn write_dumpfile(
280+
writer: &mut impl Write,
281+
fs: &FileSystem<impl FsVerityHashValue>,
282+
) -> Result<()> {
280283
// default pipe capacity on Linux is 16 pages (65536 bytes), but
281284
// sometimes the BufWriter will write more than its capacity...
282285
let mut buffer = BufWriter::with_capacity(32768, writer);

src/erofs/reader.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::{
1212
InodeXAttrHeader, ModeField, Superblock, XAttrHeader,
1313
},
1414
};
15-
use crate::fsverity::Sha256HashValue;
15+
use crate::fsverity::FsVerityHashValue;
1616

1717
pub fn round_up(n: usize, to: usize) -> usize {
1818
(n + to - 1) & !(to - 1)
@@ -486,13 +486,13 @@ pub enum ErofsReaderError {
486486
type ReadResult<T> = Result<T, ErofsReaderError>;
487487

488488
#[derive(Debug)]
489-
pub struct ObjectCollector {
489+
pub struct ObjectCollector<ObjectID: FsVerityHashValue> {
490490
visited_nids: HashSet<u64>,
491491
nids_to_visit: BTreeSet<u64>,
492-
objects: HashSet<Sha256HashValue>,
492+
objects: HashSet<ObjectID>,
493493
}
494494

495-
impl ObjectCollector {
495+
impl<ObjectID: FsVerityHashValue> ObjectCollector<ObjectID> {
496496
fn visit_xattr(&mut self, attr: &XAttr) {
497497
// This is the index of "trusted". See XATTR_PREFIXES in format.rs.
498498
if attr.header.name_index != 4 {
@@ -552,7 +552,7 @@ impl ObjectCollector {
552552
}
553553
}
554554

555-
pub fn collect_objects(image: &[u8]) -> ReadResult<HashSet<Sha256HashValue>> {
555+
pub fn collect_objects<ObjectID: FsVerityHashValue>(image: &[u8]) -> ReadResult<HashSet<ObjectID>> {
556556
let img = Image::open(image);
557557
let mut this = ObjectCollector {
558558
visited_nids: HashSet::new(),

src/erofs/writer.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,21 @@ struct Directory<'a> {
8282
}
8383

8484
#[derive(Debug)]
85-
struct Leaf<'a> {
86-
content: &'a image::LeafContent,
85+
struct Leaf<'a, ObjectID: FsVerityHashValue> {
86+
content: &'a image::LeafContent<ObjectID>,
8787
nlink: usize,
8888
}
8989

9090
#[derive(Debug)]
91-
enum InodeContent<'a> {
91+
enum InodeContent<'a, ObjectID: FsVerityHashValue> {
9292
Directory(Directory<'a>),
93-
Leaf(Leaf<'a>),
93+
Leaf(Leaf<'a, ObjectID>),
9494
}
9595

96-
struct Inode<'a> {
96+
struct Inode<'a, ObjectID: FsVerityHashValue> {
9797
stat: &'a image::Stat,
9898
xattrs: InodeXAttrs,
99-
content: InodeContent<'a>,
99+
content: InodeContent<'a, ObjectID>,
100100
}
101101

102102
impl XAttr {
@@ -263,7 +263,7 @@ impl<'a> Directory<'a> {
263263
}
264264
}
265265

266-
impl Leaf<'_> {
266+
impl<ObjectID: FsVerityHashValue> Leaf<'_, ObjectID> {
267267
fn inode_meta(&self) -> (format::DataLayout, u32, u64, usize) {
268268
let (layout, u, size) = match &self.content {
269269
image::LeafContent::Regular(image::RegularFile::Inline(data)) => {
@@ -299,7 +299,7 @@ impl Leaf<'_> {
299299
}
300300
}
301301

302-
impl Inode<'_> {
302+
impl<ObjectID: FsVerityHashValue> Inode<'_, ObjectID> {
303303
fn file_type(&self) -> format::FileType {
304304
match &self.content {
305305
InodeContent::Directory(..) => format::FileType::Directory,
@@ -395,13 +395,13 @@ impl Inode<'_> {
395395
}
396396
}
397397

398-
struct InodeCollector<'a> {
399-
inodes: Vec<Inode<'a>>,
400-
hardlinks: HashMap<*const image::Leaf, usize>,
398+
struct InodeCollector<'a, ObjectID: FsVerityHashValue> {
399+
inodes: Vec<Inode<'a, ObjectID>>,
400+
hardlinks: HashMap<*const image::Leaf<ObjectID>, usize>,
401401
}
402402

403-
impl<'a> InodeCollector<'a> {
404-
fn push_inode(&mut self, stat: &'a image::Stat, content: InodeContent<'a>) -> usize {
403+
impl<'a, ObjectID: FsVerityHashValue> InodeCollector<'a, ObjectID> {
404+
fn push_inode(&mut self, stat: &'a image::Stat, content: InodeContent<'a, ObjectID>) -> usize {
405405
let mut xattrs = InodeXAttrs::default();
406406

407407
// We need to record extra xattrs for some files. These come first.
@@ -442,7 +442,7 @@ impl<'a> InodeCollector<'a> {
442442
inode
443443
}
444444

445-
fn collect_leaf(&mut self, leaf: &'a Rc<image::Leaf>) -> usize {
445+
fn collect_leaf(&mut self, leaf: &'a Rc<image::Leaf<ObjectID>>) -> usize {
446446
let nlink = Rc::strong_count(leaf);
447447

448448
if nlink > 1 {
@@ -481,7 +481,7 @@ impl<'a> InodeCollector<'a> {
481481
entries.insert(point, entry);
482482
}
483483

484-
fn collect_dir(&mut self, dir: &'a image::Directory, parent: usize) -> usize {
484+
fn collect_dir(&mut self, dir: &'a image::Directory<ObjectID>, parent: usize) -> usize {
485485
// The root inode number needs to fit in a u16. That more or less compels us to write the
486486
// directory inode before the inode of the children of the directory. Reserve a slot.
487487
let me = self.push_inode(&dir.stat, InodeContent::Directory(Directory::default()));
@@ -509,7 +509,7 @@ impl<'a> InodeCollector<'a> {
509509
me
510510
}
511511

512-
pub fn collect(fs: &'a image::FileSystem) -> Vec<Inode<'a>> {
512+
pub fn collect(fs: &'a image::FileSystem<ObjectID>) -> Vec<Inode<'a, ObjectID>> {
513513
let mut this = Self {
514514
inodes: vec![],
515515
hardlinks: HashMap::new(),
@@ -525,7 +525,7 @@ impl<'a> InodeCollector<'a> {
525525

526526
/// Takes a list of inodes where each inode contains only local xattr values, determines which
527527
/// xattrs (key, value) pairs appear more than once, and shares them.
528-
fn share_xattrs(inodes: &mut [Inode]) -> Vec<XAttr> {
528+
fn share_xattrs<ObjectID: FsVerityHashValue>(inodes: &mut [Inode<ObjectID>]) -> Vec<XAttr> {
529529
let mut xattrs: BTreeMap<XAttr, usize> = BTreeMap::new();
530530

531531
// Collect all xattrs from the inodes
@@ -563,7 +563,11 @@ fn share_xattrs(inodes: &mut [Inode]) -> Vec<XAttr> {
563563
xattrs.into_keys().collect()
564564
}
565565

566-
fn write_erofs(output: &mut impl Output, inodes: &[Inode], xattrs: &[XAttr]) {
566+
fn write_erofs<ObjectID: FsVerityHashValue>(
567+
output: &mut impl Output,
568+
inodes: &[Inode<ObjectID>],
569+
xattrs: &[XAttr],
570+
) {
567571
// Write composefs header
568572
output.note_offset(Offset::Header);
569573
output.write_struct(format::ComposefsHeader {
@@ -684,7 +688,7 @@ impl Output for FirstPass {
684688
}
685689
}
686690

687-
pub fn mkfs_erofs(fs: &image::FileSystem) -> Box<[u8]> {
691+
pub fn mkfs_erofs<ObjectID: FsVerityHashValue>(fs: &image::FileSystem<ObjectID>) -> Box<[u8]> {
688692
// Create the intermediate representation: flattened inodes and shared xattrs
689693
let mut inodes = InodeCollector::collect(fs);
690694
let xattrs = share_xattrs(&mut inodes);

0 commit comments

Comments
 (0)