refactor for realmfs implementation

This commit is contained in:
Bruce Leidl 2019-01-30 14:21:54 -05:00
parent e5d0b7f6f2
commit 884d056420

View File

@ -94,6 +94,8 @@ impl ResourceImage {
}
fn new(path: &Path, header: ImageHeader, metainfo: MetaInfo) -> ResourceImage {
assert_eq!(path.extension(), Some(OsStr::new("img")), "image filename must have .img extension");
ResourceImage {
path: path.to_owned(),
header, metainfo,
@ -122,36 +124,21 @@ impl ResourceImage {
if !self.is_compressed() {
return Ok(())
}
let tmpfile = self.extract_body_to_tmpfile()?;
let decompressed = self.decompress_tmpfile(tmpfile)?;
self.header.clear_flag(ImageHeader::FLAG_DATA_COMPRESSED);
self.write_image_from_tmpfile(&decompressed)?;
Ok(())
}
fn decompress_tmpfile(&self, tmpfile: PathBuf) -> Result<PathBuf> {
info!("Decompressing image contents");
if !self.is_compressed() {
return Ok(tmpfile);
}
util::xz_decompress(&tmpfile)?;
let mut new_tmpfile = PathBuf::from(tmpfile);
new_tmpfile.set_extension("");
Ok(new_tmpfile)
}
fn extract_body_to_tmpfile(&self) -> Result<PathBuf> {
let mut reader = File::open(&self.path)?;
info!("decompressing image file {}", self.path().display());
let mut reader = File::open(self.path())?;
reader.seek(SeekFrom::Start(4096))?;
fs::create_dir_all("/tmp/citadel-image-tmp")?;
let mut path = Path::new("/tmp/citadel-image-tmp").join(format!("{}-tmp", &self.metainfo.image_type()));
if self.is_compressed() {
path.set_extension("xz");
}
let mut out = File::create(&path)?;
let xzfile = self.path.with_extension("tmp.xz");
let mut out = File::create(&xzfile)?;
io::copy(&mut reader, &mut out)?;
Ok(path)
util::xz_decompress(xzfile)?;
fs::rename(self.path.with_extension("tmp"), self.path())?;
self.header.clear_flag(ImageHeader::FLAG_DATA_COMPRESSED);
self.header.write_header_to(self.path())?;
Ok(())
}
pub fn write_to_partition(&self, partition: &Partition) -> Result<()> {
@ -174,15 +161,6 @@ impl ResourceImage {
Ok(())
}
fn write_image_from_tmpfile(&self, tmpfile: &Path) -> Result<()> {
let mut reader = File::open(&tmpfile)?;
let mut out = File::create(self.path())?;
self.header.write_header(&mut out)?;
io::copy(&mut reader, &mut out)?;
fs::remove_file(tmpfile)?;
Ok(())
}
fn mount_verity(&self) -> Result<()> {
let verity_dev = self.setup_verity_device()?;
@ -209,23 +187,20 @@ impl ResourceImage {
if !self.has_verity_hashtree() {
self.generate_verity_hashtree()?;
}
verity::setup_image_device(self.path())
verity::setup_image_device(self.path(), self.metainfo())
}
pub fn generate_verity_hashtree(&self) -> Result<()> {
if self.has_verity_hashtree() {
return Ok(())
}
info!("Generating dm-verity hash tree for image {}", self.path.display());
let mut tmp = self.extract_body_to_tmpfile()?;
if self.is_compressed() {
tmp = self.decompress_tmpfile(tmp)?;
self.header.clear_flag(ImageHeader::FLAG_DATA_COMPRESSED);
self.decompress()?;
}
verity::generate_image_hashtree(&tmp, self.metainfo())?;
info!("Generating dm-verity hash tree for image {}", self.path.display());
verity::generate_image_hashtree(self.path(), self.metainfo())?;
self.header.set_flag(ImageHeader::FLAG_HASH_TREE);
self.write_image_from_tmpfile(&tmp)?;
self.header.write_header_to(self.path())?;
Ok(())
}
@ -234,27 +209,20 @@ impl ResourceImage {
self.generate_verity_hashtree()?;
}
info!("Verifying dm-verity hash tree");
let tmp = self.extract_body_to_tmpfile()?;
let ok = verity::verify_image(&tmp, &self.metainfo)?;
fs::remove_file(tmp)?;
Ok(ok)
verity::verify_image(self.path(), self.metainfo())
}
pub fn generate_shasum(&self) -> Result<String> {
let mut tmp = self.extract_body_to_tmpfile()?;
if self.is_compressed() {
tmp = self.decompress_tmpfile(tmp)?;
self.decompress()?;
}
info!("Calculating sha256 of image");
if self.has_verity_hashtree() {
let args = format!("if={} of={}.shainput bs=4096 count={}", tmp.display(), tmp.display(), self.metainfo.nblocks());
util::exec_cmdline_quiet("/bin/dd", args)?;
fs::remove_file(&tmp)?;
tmp.set_extension("shainput");
}
let shasum = util::sha256(&tmp)?;
fs::remove_file(tmp)?;
let output = util::exec_cmdline_pipe_input("sha256sum", "-", self.path(), util::FileRange::Range{offset: 4096, len: self.metainfo.nblocks() * 4096})
.context(format!("failed to calculate sha256 on {}", self.path().display()))?;
let v: Vec<&str> = output.split_whitespace().collect();
let shasum = v[0].trim().to_owned();
Ok(shasum)
}
// Mount the resource image but use a simple loop mount rather than setting up a dm-verity
@ -278,15 +246,19 @@ impl ResourceImage {
}
pub fn create_loopdev(&self) -> Result<PathBuf> {
let args = format!("--offset 4096 -f --show {}", self.path.display());
let args = format!("--offset 4096 -f --read-only --show {}", self.path.display());
let output = util::exec_cmdline_with_output("/sbin/losetup", args)?;
Ok(PathBuf::from(output))
}
// Return the path at which to mount this resource image.
fn mount_path(&self) -> PathBuf {
if self.metainfo.image_type() == "realmfs" {
PathBuf::from(format!("{}/{}-realmfs.mountpoint", RUN_DIRECTORY, self.metainfo.realmfs_name().expect("realmfs image has no name")))
} else {
PathBuf::from(format!("{}/{}.mountpoint", RUN_DIRECTORY, self.metainfo.image_type()))
}
}
// Read and process a manifest file in the root directory of a mounted resource image.
fn process_manifest_file(&self) -> Result<()> {
@ -333,7 +305,7 @@ impl ResourceImage {
// If the /storage directory is not mounted, attempt to mount it.
// Return true if already mounted or if the attempt to mount it succeeds.
fn ensure_storage_mounted() -> Result<bool> {
if Mount::is_path_mounted("/dev/mapper/citadel-storage")? {
if Mount::is_source_mounted("/dev/mapper/citadel-storage")? {
return Ok(true);
}
let path = Path::new("/dev/mapper/citadel-storage");