refactor for realmfs implementation
This commit is contained in:
parent
e5d0b7f6f2
commit
884d056420
@ -94,6 +94,8 @@ impl ResourceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new(path: &Path, header: ImageHeader, metainfo: MetaInfo) -> 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 {
|
ResourceImage {
|
||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
header, metainfo,
|
header, metainfo,
|
||||||
@ -122,36 +124,21 @@ impl ResourceImage {
|
|||||||
if !self.is_compressed() {
|
if !self.is_compressed() {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
info!("decompressing image file {}", self.path().display());
|
||||||
let tmpfile = self.extract_body_to_tmpfile()?;
|
let mut reader = File::open(self.path())?;
|
||||||
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)?;
|
|
||||||
reader.seek(SeekFrom::Start(4096))?;
|
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()));
|
let xzfile = self.path.with_extension("tmp.xz");
|
||||||
if self.is_compressed() {
|
let mut out = File::create(&xzfile)?;
|
||||||
path.set_extension("xz");
|
|
||||||
}
|
|
||||||
let mut out = File::create(&path)?;
|
|
||||||
io::copy(&mut reader, &mut out)?;
|
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<()> {
|
pub fn write_to_partition(&self, partition: &Partition) -> Result<()> {
|
||||||
@ -174,15 +161,6 @@ impl ResourceImage {
|
|||||||
Ok(())
|
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<()> {
|
fn mount_verity(&self) -> Result<()> {
|
||||||
let verity_dev = self.setup_verity_device()?;
|
let verity_dev = self.setup_verity_device()?;
|
||||||
|
|
||||||
@ -209,23 +187,20 @@ impl ResourceImage {
|
|||||||
if !self.has_verity_hashtree() {
|
if !self.has_verity_hashtree() {
|
||||||
self.generate_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<()> {
|
pub fn generate_verity_hashtree(&self) -> Result<()> {
|
||||||
if self.has_verity_hashtree() {
|
if self.has_verity_hashtree() {
|
||||||
return Ok(())
|
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() {
|
if self.is_compressed() {
|
||||||
tmp = self.decompress_tmpfile(tmp)?;
|
self.decompress()?;
|
||||||
self.header.clear_flag(ImageHeader::FLAG_DATA_COMPRESSED);
|
|
||||||
}
|
}
|
||||||
|
info!("Generating dm-verity hash tree for image {}", self.path.display());
|
||||||
verity::generate_image_hashtree(&tmp, self.metainfo())?;
|
verity::generate_image_hashtree(self.path(), self.metainfo())?;
|
||||||
self.header.set_flag(ImageHeader::FLAG_HASH_TREE);
|
self.header.set_flag(ImageHeader::FLAG_HASH_TREE);
|
||||||
self.write_image_from_tmpfile(&tmp)?;
|
self.header.write_header_to(self.path())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,27 +209,20 @@ impl ResourceImage {
|
|||||||
self.generate_verity_hashtree()?;
|
self.generate_verity_hashtree()?;
|
||||||
}
|
}
|
||||||
info!("Verifying dm-verity hash tree");
|
info!("Verifying dm-verity hash tree");
|
||||||
let tmp = self.extract_body_to_tmpfile()?;
|
verity::verify_image(self.path(), self.metainfo())
|
||||||
let ok = verity::verify_image(&tmp, &self.metainfo)?;
|
|
||||||
fs::remove_file(tmp)?;
|
|
||||||
Ok(ok)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_shasum(&self) -> Result<String> {
|
pub fn generate_shasum(&self) -> Result<String> {
|
||||||
let mut tmp = self.extract_body_to_tmpfile()?;
|
|
||||||
if self.is_compressed() {
|
if self.is_compressed() {
|
||||||
tmp = self.decompress_tmpfile(tmp)?;
|
self.decompress()?;
|
||||||
}
|
}
|
||||||
info!("Calculating sha256 of image");
|
info!("Calculating sha256 of image");
|
||||||
if self.has_verity_hashtree() {
|
let output = util::exec_cmdline_pipe_input("sha256sum", "-", self.path(), util::FileRange::Range{offset: 4096, len: self.metainfo.nblocks() * 4096})
|
||||||
let args = format!("if={} of={}.shainput bs=4096 count={}", tmp.display(), tmp.display(), self.metainfo.nblocks());
|
.context(format!("failed to calculate sha256 on {}", self.path().display()))?;
|
||||||
util::exec_cmdline_quiet("/bin/dd", args)?;
|
let v: Vec<&str> = output.split_whitespace().collect();
|
||||||
fs::remove_file(&tmp)?;
|
let shasum = v[0].trim().to_owned();
|
||||||
tmp.set_extension("shainput");
|
|
||||||
}
|
|
||||||
let shasum = util::sha256(&tmp)?;
|
|
||||||
fs::remove_file(tmp)?;
|
|
||||||
Ok(shasum)
|
Ok(shasum)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount the resource image but use a simple loop mount rather than setting up a dm-verity
|
// 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> {
|
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)?;
|
let output = util::exec_cmdline_with_output("/sbin/losetup", args)?;
|
||||||
Ok(PathBuf::from(output))
|
Ok(PathBuf::from(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the path at which to mount this resource image.
|
// Return the path at which to mount this resource image.
|
||||||
fn mount_path(&self) -> PathBuf {
|
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()))
|
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.
|
// Read and process a manifest file in the root directory of a mounted resource image.
|
||||||
fn process_manifest_file(&self) -> Result<()> {
|
fn process_manifest_file(&self) -> Result<()> {
|
||||||
@ -333,7 +305,7 @@ impl ResourceImage {
|
|||||||
// If the /storage directory is not mounted, attempt to mount it.
|
// If the /storage directory is not mounted, attempt to mount it.
|
||||||
// Return true if already mounted or if the attempt to mount it succeeds.
|
// Return true if already mounted or if the attempt to mount it succeeds.
|
||||||
fn ensure_storage_mounted() -> Result<bool> {
|
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);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
let path = Path::new("/dev/mapper/citadel-storage");
|
let path = Path::new("/dev/mapper/citadel-storage");
|
||||||
|
Loading…
Reference in New Issue
Block a user